Using pugixml to read an entire xml file

236 Views Asked by At

I know there's already a way to loop through a file with pugi::xml_node::traverse, but I'm very interested in how things work, so I want to reimplement it using a recursive function. Currently, I can only parse the first depth of the function because I don't know how to detect whether the current item has children (next_siblings returns an invalid value).

// TODO: use std::ostringstream instead of std::string
void MyClass::recursive(const pugi::xml_node& start, std::string& output) 
{
    // Check for invalid node
    if (!start.first_child() || (!start.next_sibling() && start.parent() != start.parent())) {
        return;
    }
    // Process the current node
    for (auto node : start.children()) {
        output += node.name();
        output += "\n";
        for (auto attribute : node.attributes()) {
            output += "Attribute Name : ";
            output += attribute.name();
            output += ", Attribute Value = ";
            output += attribute.value();
            output += " ";
        }
        output += "\n";
        const char* PCDATA = node.child_value();
        output += PCDATA == "" ? "[no pcdata]"
                               : PCDATA;
        if (node.first_child()) {
            recursive(node, output);
        }
        else {
            recursive(node.next_sibling(), output);
        }
    }
}

Sample XML file

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <child1>
        <sub name="attr1">value</sub>
        <sub name="attr2">value</sub>
        <sub name="attr3">value</sub>
    </child1>
    <child2>
        <sub name="attr1">value</sub>
        <sub name="attr2">value</sub>
        <sub name="attr3">value</sub>
    </child2>
    <child3>
        <sub name="attr1">value</sub>
        <sub_with_children>
            <child1 name="[]">value</sub>
            <child2 name="[]">value</sub>
            <child3 name="[]">value</sub>
        </sub_with_children>
    </child3>
    <child4>
        <sub name="attr1">value</sub>
        <sub name="attr2">value</sub>
    </child4>
</root>

Edit: the code above is now working

0

There are 0 best solutions below