I'm trying to edit the value of a node using RapidXML 1.13 but the changes aren't made to the .xml file.
A simplified version of the XML file looks like this:
<users>
<user>
<username>test</username>
<!-- This hazard line should change to "true" -->
<hazards>false</hazards>
<weather>false</weather>
</user>
</users>
I use a simple for to iterate through all users. When the matching one is found, I select the attribute I am interested in and try to modify its content.
rapidxml::file<> xmlFile("users.xml");
rapidxml::xml_document<> doc;
doc.parse<0>(xmlFile.data());
for (rapidxml::xml_node<>* userNode = doc.first_node("users")->first_node("user"); userNode; userNode = userNode->next_sibling("user"))
{
rapidxml::xml_node<>* usernameNode = userNode->first_node("username");
if (usernameNode && strcmp(usernameNode->value(), username) == 0)
{
rapidxml::xml_node<>* settingNode = userNode->first_node(setting.c_str());
if (settingNode)
{
// Here's the problem
settingNode->value(doc.allocate_string(boolToChar(value)));
std::ofstream outFile("users.xml");
outFile << doc;
outFile.close();
std::cout << settingNode->value() << std::endl;
rapidxml::print(std::cout, doc, 0);
return; // Don't keep the for running
}
}
// Other edge cases...
}
This line std::cout << settingNode->value() << std::endl; prints "true" (the correct new value), but this rapidxml::print(std::cout, doc, 0); prints the old, unchanged XML file. Therefore, the value seems to be modified, but never saved into the doc file.
I've tried to create a clone of the node, delete the original and insert the modified clone, but the same problem occurs: can't change the value.
boolToChar() function is correct, the exact same method works when trying to use allocate_string() to a new generated node.
EDIT
Found the problem: This line settingNode->value(doc.allocate_string(boolToChar(value))); transforms to settingNode->first_node()->value(doc.allocate_string(boolToChar(value)));. From what I can tell, the text inside the nodes are considered nodes too, thus explaining the first_node() extra call.
Here is XSLT based solution. One single template does the job.
There are few libraries available for XSLT in c++.
Input XML
XSLT 1.0
Output XML