Deleting specific node of XML file - c++

Below I have a sample of my XML file, I want to delete a specific node in each header. How do i do it. for example in header<HEADER> i want to delete the node <ADDRESS>, not just its attribute but the whole node. in <HEADER1> I need to delete the attribute <UMG_VAR Name="ABC" Value=1></UMG_var>, here Name attribute is unique.
<MAIN>
<HEADER>
<TITLE>ppc_ph_pios</TITLE>
<AUTOR>DNL</AUTOR>
<AGE>age</AGE>
<SEX>Male</SEX>
<PLACE>Earth</PLACE>
<ADDRESS>abc</ADDRESS>
</HEADER>
<HEADER1>
<UMG_VAR Name="RED" Value="3"></UMG_VAR>
<UMG_VAR Name="ABC2" Value="2"></UMG_VAR>
<UMG_VAR Name="ABC" Value="1"></UMG_VAR>
</HEADER2>
</MAIN>

QDomDocument doc;
doc.setContent(oldXml);
QDomNodeList nodes = doc.elementsByTagName("element");
for (int i = 0; i < nodes.count(); ++i)
{
QDomNode node = nodes.at(i);
QDomElement child = node.firstChildElement("child");
if (!child.isNull() && child.attribute("id") == "0")
{
node.removeChild(child);
}
}
QString newXml = doc.toString();

Related

Remove child nodes from parent - PugiXML

<Node>
<A>
<B id = "it_DEN"></B>
</A>
<A>
<B id = "en_KEN"></B>
</A>
<A>
<B id = "it_BEN"></B>
</A>
</Node>
How can I remove child node of <A></A> that has child node <B></B> which has attribute id not starts with it using PugiXML.
The result would be as below:
<Node>
<A>
<B id = "it_DEN"></B>
</A>
<A>
<B id = "it_BEN"></B>
</A>
</Node>
This is slightly tricky if you want to remove nodes while iterating (to keep the code single-pass). Here's one way to do it:
bool should_remove(pugi::xml_node node)
{
const char* id = node.child("B").attribute("id").value();
return strncmp(id, "it_", 3) != 0;
}
for (pugi::xml_node child = doc.child("Node").first_child(); child; )
{
pugi::xml_node next = child.next_sibling();
if (should_remove(child))
child.parent().remove_child(child);
child = next;
}
Alternatively you can just use XPath and remove the results:
pugi::xpath_node_set ns = doc.select_nodes("/Node/A[B[not(starts-with(#id, 'it_'))]]");
for (auto& n: ns)
n.node().parent().remove_child(n.node());
Another way is to increment the iterator before removing the child. To remove an attribute while iterating.
for(pugi::xml_attribute_iterator it = node.attributes_begin(); it != node.attributes_end();){
pugi::xml_attribute attr = *it++;
if(should_remove(attr)){
node.remove_attribute(attr);
}
}

Reading child node of a child node

Below i have show a normal XML file:
<Header>
<Sub Name="" Value="" /Sub>
<Sub Name="" value="" /Sub>
.
.
.
.
</Header>
I read the above mentioned XML like this:
QStringList Name;
QStringList value;
QXmlGet xmlget;
xmlget.load(Sample.xml);
xmlget.findAndDescend("Header");
while(xmlget.findNext("Sub")
{
Name.append(xmlget.getAttributeString("Name". "Unknown"));
value.append(xmlget.getAttributeString("value". "Unknown"));
}
xmlget.save(Sample.xml);
But the xml i have right now is bit complicated.
XML:
<Header>
<Sub Name= "" Value = ""><Sub1 Name = ""></Sub1></Sub>
<Sub Name= "" value = "" /Sub>
<Sub Name= "" Value = ""><Sub1 Name = ""></Sub1></Sub>
.
.
.
</Header>
Any suggestions how do I read the <Sub1>
Something like this one (Tested! It works!)
QStringList Name;
QStringList value;
QXmlGet xmlget;
xmlget.load("Sample.xml");
xmlget.findAndDescend("Header");
QXmlPut xmlPut(xmlget); // init reference from the variable - xmlget
while(xmlget.findNext("Sub")) {
Name.append(xmlget.getAttributeString("Name", "Unknown"));
value.append(xmlget.getAttributeString("Value", "Unknown"));
xmlget.descend(); // now Sub is the parent element
if( xmlPut.hasChildren() ) {
while(xmlget.findNext("Sub1") { // finding relatively the parent - Sub
xmlPut.goTo(xmlget.element());
xmlPut.setAttributeString("Name", "NAME1");
xmlPut.setAttributeString("Value", "VALUE1");
}
} else {
xmlPut.putInt("IntTag", "IntValue"); // We create the child node (IntTag) of the parent (Sub)
xmlPut.setAttributeString("AttrName", "AttrValue"); // and add some attributes to it
}
xmlget.rise();
}
xmlPut.save("Sample.xml"); // Any file name to save the xml data
docs

How to delete nested xml element using qt

i have xml file like this
<root>
<element>
<child id = "0"> Some Text </child> <-- Target To Delete
</element>
<element>
<child id = "1"> Some Text </child>
</element>
</root>
how can i delete child element of id "0" ? using Qt library.
QDomDocument doc;
doc.setContent(oldXml);
QDomNodeList nodes = doc.elementsByTagName("element");
for (int i = 0; i < nodes.count(); ++i)
{
QDomNode node = nodes.at(i);
QDomElement child = node.firstChildElement("child");
if (!child.isNull() && child.attribute("id") == "0")
{
node.removeChild(child);
}
}
QString newXml = doc.toString();

Xpath How remove child node by attribute c++ libxml2

How do I remove a child with a specific attribute? I´m using c++/libxml2. My attempt so far (in the example I want to remove child node with id="2"):
Given XML:
<p>
<parent> <--- current context
<child id="1" />
<child id="2" />
<child id="3" />
</parent>
</p>
xmlNodePtr p = (parent node)// Parent node, in my example "current context"
xmlChar* attribute = (xmlChar*)"id";
xmlChar* attribute_value = (xmlChar*)"2";
xmlChar* xml_str;
for(p=p->children; p!=NULL; p=p->next){
xml_str = xmlGetProp(p, attribute);
if(xml_str == attribute_value){
// Remove this node
}
}
xmlFree(xml_str);
Call xmlUnlinkNode to remove a node. Call xmlFreeNode to free it afterward, if you want:
for (p = p->children; p; ) {
// Use xmlStrEqual instead of operator== to avoid comparing literal addresses
if (xmlStrEqual(xml_str, attribute_value)) {
xmlNodePtr node = p;
p = p->next;
xmlUnlinkNode(node);
xmlFreeNode(node);
} else {
p = p->next;
}
}
Haven't used this library in a while, but check out this method. Note that per the description, you need to call xmlUnlinkNode first.

Why is this loop only running once?

Why is this loop only running once?
noteDatabaseItem just takes a node and fills in the data. the xml has 3 notes in it.
XML:
<?xml version="1.0" encoding="utf-8"?>
<noteCollection>
<note name="Test Note 1">This is test note 1 content!</note>
<note name="Test Note 2">This is test note 2 content!</note>
<note name="Test Note 3">This is test note 3 content!</note>
</noteCollection>
C++:
std::vector<notekeeper::noteDatabaseItem> noteList;
TiXmlElement* noteCollection = xmlDoc->FirstChildElement("noteCollection");
TiXmlElement* node = noteCollection->FirstChildElement("note");
int itemCount = 0;
while (node != NULL) {
itemCount++;
noteList.resize(itemCount);
noteList.push_back(noteDatabaseItem(node));
node = noteCollection->NextSiblingElement("note");
}
Shouldn't it be node = node->NextSiblingElement("note")?
noteCollection has only children, not siblings, right?
You're getting the wrong element in your loop. Try this:
while (node != NULL) {
itemCount++;
noteList.push_back(noteDatabaseItem(node));
node = node->NextSiblingElement("note");
}
The next sibling of the current node is the one you want. You were trying to get the next sibling of the parent node.
node = noteCollection->NextSiblingElement("note");
is meant to be
node = node->NextSiblingElement("note");
Stupid mistake. Sibling not Child.