I've been messing with XML configuration data for a simulation application I am building, and have run into some confusing problems. Firstly, I'm walking an XML tree using DOM, with Qt 4.6.2.
The XML file looks like this (settings.xml):
<?xml version='1.0' encoding="UTF-8"?>
<settings>
<configuration name="Eddie">
<execdir>Execution path of Eddie</execdir>
<path>Path to Eddie GUI</path>
<binary>Eddie GUI binary</binary>
</configuration>
</settings>
<?xml version='1.0' encoding="UTF-8"?>
<settings>
<configuration name="Eddie">
<execdir>Execution path of Eddie</execdir>
<path>Path to Eddie GUI</path>
<binary>Eddie GUI binary</binary>
</configuration>
</settings>
To copy to clipboard, switch view to plain text mode
Pretty straightforward, eh?
The problem that I'm running into is that the replaceChild will return a null QDomNode. It should point to the new old node. According to the documentation, replaceChild failed, since it is returning with a null node. I can get this code to compile and run two different ways, but the one way doesn't work.
For further clarification (from the main.cpp file):
QFile file("../src/settings.xml");
doc.setContent(&file);
if(root.tagName() != "settings")
return -3;
while(!n.isNull())
{
if(!e.isNull())
{
if((e.tagName() == "configuration") and (e.attribute("name", "") == "Eddie"))
{
if(!e2.isNull())
{
while(!e2.isNull())
{
if(e2.tagName() == "execdir")
{
// The following works... we'll call this Exhibit 1
currNode.setNodeValue("NEW DATA HERE");
// As does this portion of code... we'll call this Exhibit 2
QDomText text
= doc.
createTextNode("NEW DATA HERE");
e2.replaceChild(text, e2.firstChild());
// This DOESN'T work! It will replace this and only this instance.
// replaceChild is returning with a null QDomNode, and e2 thus
// will return true when isNull is invoked. Almost as if the nodes
// in the list aren't hooked up correctly...
//
// We'll call this Exhibit 3
elem.appendChild(doc.createTextNode("NEW DATA HERE");
n.replaceChild(elem, e2);
}
else if(e2.tagName() == "binary")
{
// This portion looks exactly the same as above, only with different
// data being pushed.
}
e2 = e2.nextSiblingElement();
}
}
}
}
n = n.nextSibling();
}
// Perform writes to the settings.xml file
file.remove();
ts<<doc.toString(4);
file.close();
QDomDocument doc("stuffage");
QFile file("../src/settings.xml");
doc.setContent(&file);
QDomElement root = doc.documentElement();
if(root.tagName() != "settings")
return -3;
QDomNode n = root.firstChild();
while(!n.isNull())
{
QDomElement e = n.toElement();
if(!e.isNull())
{
if((e.tagName() == "configuration") and (e.attribute("name", "") == "Eddie"))
{
QDomElement e2 = n.firstChildElement();
if(!e2.isNull())
{
while(!e2.isNull())
{
if(e2.tagName() == "execdir")
{
// The following works... we'll call this Exhibit 1
QDomNode currNode = e2.firstChild();
currNode.setNodeValue("NEW DATA HERE");
// As does this portion of code... we'll call this Exhibit 2
QDomText text = doc.createTextNode("NEW DATA HERE");
e2.replaceChild(text, e2.firstChild());
// This DOESN'T work! It will replace this and only this instance.
// replaceChild is returning with a null QDomNode, and e2 thus
// will return true when isNull is invoked. Almost as if the nodes
// in the list aren't hooked up correctly...
//
// We'll call this Exhibit 3
QDomElement elem = doc.createElement("execdir");
elem.appendChild(doc.createTextNode("NEW DATA HERE");
n.replaceChild(elem, e2);
}
else if(e2.tagName() == "binary")
{
// This portion looks exactly the same as above, only with different
// data being pushed.
}
e2 = e2.nextSiblingElement();
}
}
}
}
n = n.nextSibling();
}
// Perform writes to the settings.xml file
file.remove();
file.open(QIODevice::ReadWrite);
QTextStream ts(&file);
ts<<doc.toString(4);
file.close();
To copy to clipboard, switch view to plain text mode
I'm just trying to figure out how I can replace an existing tag with data in it on the fly. I want to be able to look at an element, determine if it is needing changed, and if it does, change it, and move to the next element to perform the same logic (check if it needs changed, change it, then move on again).
As stated above, Exhibit 1 and 2 work, but not 3. It's like I'm deleting something from an STL list, but didn't reset the iterator to the new position.
So for further clarification, I do not have Exhibit 1, 2, and 3 all together. Only one or the other is being used. I am looking at two tags that are going to need to be updated whenever configuration settings change on a child form. Therefore, I need to incrementally make my changes, then shove them off to a .xml flat-file. I can do this by performing a setNodeValue on the QDomText of each of the execdir, path, and binary tags. I can also create a text node, and replace the text node currently contained within the execdir, path, and binary tags. I can do this with all the elements that are in the tree. In other words, if I only had one tag, it would work for that one tag. If I had fifty, then it would work for all fifty. However, if I attempt Exhibit 3, it would change only the first match, then exit out of the loop, since e2 is null.
Any suggestions?
Bookmarks