0

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

2
  • 1
    This does not look like a properly-formed recursive function. The usual way would be to return immediately if the node is not valid, otherwise process the node's own contents, then perform a recursive call on each child of that node. There should be no reason to iterate through siblings. Commented Jul 28, 2022 at 23:15
  • Got it, thank you very much! I'm a beginner at this library, and this function was the occasion for me to write a recursive function since I never had any case where I needed such a thing. An update has been made to the original question in case someone have something to say about the new code. Commented Jul 29, 2022 at 20:37

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.