I am confused as to why I can find the node by name through next_sibling. But when I try to use first_node I am getting a segfault.
The parent node containing all the nodes I need to find.
rapidxml::xml_node<> *xmlnode_chd = xml_doc->first_node();
The two lines to access the node
xmlnode_chd->first_node()->next_sibling("name_to_find")->name(); //Works
xmlnode_chd->first_node("name_to_find")->name(); //Fails
To my understanding a sibling node has the same parent. I thought that the logic between these two statements was the same. I am probably overlooking something simple.
Related
I want to configure a device using an XML file and was thinking that I can make the individual pugi::xml_nodes first with the values I need and later on make them children of a document or some parent node. However, I seem to be doing something wrong.
Example that works:
#include "pugixml.hpp"
int main(){
pugi::xml_document xml;
pugi::xml_node configRecord = xml.append_child("configrecord");
pugi::xml_node configGroup = configRecord.append_child("configgroup");
configGroup.append_attribute("name") = "ftp server";
}
This works because I first create the parent document and then start branching by adding children. I was thinking that I can first make the node objects, store them into an array and parse that array to add them to the document. But this doesn't work.
#include "pugixml.hpp"
int main(){
pugi::xml_node myNode;
myNode.set_name("value");
myNode.append_child(pugi::node_pcdata).set_value("enable");
pugi::xml_document docu;
docu.set_name("document");
docu.child(myNode); // <- error here, cannot add child to document
}
Can I somehow use the strategy I was planning to or am I constrained to only adding children to an existing parent?
pugixml documentation states that pugi::xml_node is a non-owning pointer to actual node data stored in a pugi::xml_document object:
xml_node is the handle to document node; it can point to any node in
the document, including the document node itself. There is a common
interface for nodes of all types; the actual node type can be queried
via the xml_node::type() method. Note that xml_node is only a handle
to the actual node, not the node itself
Nodes and attributes do not exist without a document tree, so you
can’t create them without adding them to some document.
It seems to me that your code doesn't throw errors when you try to manipulate myNode because default-constructed "null" nodes silently consume operations on them to make chaining easier:
all operations are defined on empty nodes; generally the operations
don’t do anything and return empty nodes/attributes or empty strings
as their result [...] This is useful for chaining calls
i'm currently working with xerces 3.1 in visual studio 2010.
I've written this (very simple) piece of code:
XMLPlatformUtils::Initialize();
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(L"XML 1.0");
DOMDocument* doc1 = impl->createDocument(L"nsURI", L"abc:root1", 0);
DOMDocument* doc2 = impl->createDocument(0, L"root2", 0);
DOMElement* root1 = doc1->getDocumentElement();
DOMElement* root2 = doc2->getDocumentElement();
DOMElement* el1 = doc1->createElement(L"el1");
root1->appendChild(el1);
DOMNode* tmpNode = doc2->adoptNode(el1); //tmpNode is null after this line
root2->appendChild(tmpNode);
doc1->release();
doc2->release();
xercesc::XMLPlatformUtils::Terminate();
The problem is, the adoptNode(...) method will always return a null-pointer no matter what. I really don't understand what's going on here, please help me!
PS: I know i could use the importNode(...) method and remove and release the old node from the old document, but i was hoping there was a way to fix my problem with adoptNode(...)!
The xerces api states the following for adoptNode(DOMNode* source):
Changes the ownerDocument of a node, its children, as well as the attached attribute nodes if there are any.
After some research i took a look at the implementation of adoptNode in xerces 3.1 and the sad truth is that it's not possible. Quoting the sourcecode:
if(sourceNode->getOwnerDocument()!=this)
{
// cannot take ownership of a node created by another document, as it comes from its memory pool
// and would be delete when the original document is deleted
return 0;
}
EDIT:
There is a workaround for this method but it requires some knowledge of the DOM-Implementation (especially when using UserData). You can import the node with importNode(...) and delete the other node out of the old document.
The old nodes should be released in order to not waste memory!
If you've got userdata attached to the old nodes, the new document has to have some UserDataHandler which adopts the userdata from the old node to the new node!
Please note that possible references on the old nodes do not point onto the new nodes now. They'll have to be changed manually (or with some UserDataHandler workaround)
I found a memory leak in my application using libxml++ due to an XML document where I replace the root node. I took good care for removing any child nodes, but using the xmlpp::Document interface I find no way to replace the root node.
This is a sample of the offending code:
xmlpp::Document Doc;
Doc.create_root_node("root");
// Populate the document
// [...]
void ReplaceRootNode(const xmlpp::Element* NewRootNode)
{
// Remove all root node children
xmlpp::Element* RootNode = Doc.get_root_node();
const xmlpp::Node::NodeList Children = RootNode->get_children();
xmlpp::Node::NodeList::const_iterator itChild = Children.begin();
while (itChild != Children.end()) {
RootNode->remove_child(*itChild++);
}
// Replace root node
Doc.create_root_node_by_import(NewRootNode); // Leak: memory for previous root node is not freed
}
The solution I came up with so far is to edit the document's root node to change it's name and attributes but. Is there a simpler way to avoid this leak which does not involve edition of previous root node's name and attributes?
I work around this by setting the document to an empty Document object (Doc = xmlpp:Document()) before calling create_root_node_by_import instead of removing the root's child nodes explicitly. This appears to cause the previous contents of Doc to be freed.
I first encountered this problem several years ago, and it still does not appear to be fixed in recent versions of libxml++. Surely they must be aware of it. Could this case somehow be using create_root_node_by_import in an unintended fashion? I would not have thought so, but OTOH this seems too important not to fix.
I have a c++ application that manipulates xml.
Well, at a certain point of my application I get a DOMNode* and then I attach it to an element as a child.
Well the problem is that I would like to add parameters to that node... well it is a node so it is not an element... only elements have parameters...
This is my code:
xercesc::DOMNode* node = 0;
std::string xml = from_an_obj_of_mine.GetXml(); /* A string with xml inside, the xml is sure an element having something inside */
xercesc::MemBufInputSource xml_buf((const XMLByte*)xml.c_str(), xml.size(), "dummy");
xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser();
parser->parse(xml_buf); /* parser will contain a DOMDocument well parsed from the string, I get here the node i want to attach */
node = my_pointer_to_a_preexisting_domdocument->GetXmlDocument()->importNode(parser->getDocument()->getDocumentElement(), true); /* I want to attach the node in parser to a node of my_pointer_to_an_el_of_my_preexisting_domdocument, it is a different tree, so I must import the node to attach it later */
my_pointer_to_an_el_of_my_preexisting_domdocument->appendChild(node);
As you can see I want to create a node from a string, I create it through a parse and then need to import the node to create a new identical node belonging to the dom tree where I want to attach the new node.
My steps are:
Get the xml string to attach to a pre-existing dom (stored as a domdocument somewhere)
Create a parser
Using the parser create a dom tree from the string
From my pre-existing dom (where I want to attach my new node), call the import and clone the node
so that it can be attached to the pre-existing dom.
Attach it
The problem is that import and import gets me a node... I want an element to attach...
I use appendChild to append elements too... of course the method wants DOMNode* but giving it a DOMElement* (which inherits from DOMNode) is ok...
How can I get an element from a node???
delete wd_parser;
ok I discovered it...
Just re-cast the node to element and it is done... DOMNode is a pure virtual class and it is parent of DOMElement... so it is correct and it is also the way to do things (logically speaking).
DOMElement* = dynamic_cast<DOMElement*>(node);
:)
I'm using wxWidgets 2.8.11 on Windows 7 64 Bit. I created a wxTreeCtrl control, which as the name suggests, is a tree control. You can add Root nodes by calling AddRoot(), however it seems to only work the first time of calling it.
Here is the code where I create the Tree:
newHandler-> sendPacketTree = new wxTreeCtrl(newHandler->sendGroupBox,4,wxPoint(7,12),wxSize(newHandler->sendGroupBox->GetSize().x-14,newHandler->sendGroupBox->GetSize().y-20),wxTR_DEFAULT_STYLE);
Here is what I'm doing just as a test:
this->sendPacketTree->AddRoot(wxT("Test1"));
this->sendPacketTree->AddRoot(wxT("Test2"));
However, only the first root node appears in the Tree, and the second node doesn't appear (or any other node after the first node for that matter)
Does anyone know why this is happening, or how I can get around this? I'm stumped.
I found a solution on my own. I thought that AddRoot() allowed you to add more then one root. It turns out you can only have one root, but you are able to hide the actual "root", and any children of the root will look like a root with the wxTR_HIDE_ROOT style set.