0

I've been looking for how to parse an xml file using codeblocks and the library pugixml but I've tried different ways and it still doesn't work.

The XML I have to parse consists on a graph (houses) and my program in C++ is to represent this graph using structs.

XML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<WATSON>
  <PHILIPS> 125 </PHILIPS>
  <PEREZ> 254 </PEREZ>
  <SANTOS> 222 </SANTOS>
</WATSON>
<PHILIPS>
    <CENTER> 121 </CENTER>
    <WATSON> 125 </WATSON>
    <SANTOS> 55 </SANTOS>
</PHILIPS>
<PEREZ>
    <WATSON> 254 </WATSON>
    <CENTER> 110 </CENTER>
</PEREZ>

ETC...

The code in C++: (the important part :) )

int main(){
    pugi::xml_document file;

    if (!file.load_file("Sample.xml")){
    cout << "Error loading file XML." << endl;
    system("PAUSE");
    return -1;
}
    pugi::xml_node node;
    getNodeInfo(node);
    cin.get();
    return 0;
}

void getNodeInfo(xml_node node){
    for (xml_node_iterator it = node.begin(); it != node.end(); ++it)
    {
        cout << it->name() << "\n--------\n";
        system("PAUSE");
        for (xml_attribute_iterator ait = it->attributes_begin(); ait != it->attributes_end(); ++ait)
    {
            cout << " " << ait->name() << ": " << ait->value() << endl;
    }
        cout << endl;
        for (xml_node_iterator sit = node.begin(); sit != node.end(); ++sit)
        {
            getNodeInfo(*sit);
    }
}
}

Please tell me, what could be the mistake in the code? It always goes into the if condition, I mean, it doesn't load the file. Thank you!

  • 1
    Your XML data is not well formed. There should be one enclosing tag for everything. – Galik Nov 11 '14 at 16:33
  • What does this question have to do with Codeblocks? – UpAndAdam Nov 11 '14 at 19:48
  • Thank you for your reply. I wish I could know about the XML file, because the ones I've found on Internet are different and called graphml; but this xml file format is the one the teacher suggested to work with. Codeblocks is the Idle I'm using to program on C++ and where I installed the library pugixml. – I love programming with coffee Nov 12 '14 at 01:43

1 Answers1

0

I noticed a couple of errors.

First you are sending an empty node to your function so it has nothing to work on. You should send the file you loaded instead:

int main()
{
    pugi::xml_document file;

    xml_parse_result res;
    if(!(res = file.load_file("test.xml")))
    {
        cout << "Error loading file XML: " << res.description() << endl;
        system("PAUSE");
        return -1;
    }

    pugi::xml_node node; // you are sending an EMPTY node
    // getNodeInfo(node);

    // Send the file you just loaded instead
    getNodeInfo(file);

    cin.get();
    return 0;
}

Also you have a weird loop within a loop thing going on in your function. You are already looping over the node's children, no need for the inner loop over the same children:

void getNodeInfo(xml_node node)
{
    for(xml_node_iterator it = node.begin(); it != node.end(); ++it)
    {
        cout << it->name() << "\n--------\n";
//      system("PAUSE");
        for(xml_attribute_iterator ait = it->attributes_begin();
        ait != it->attributes_end(); ++ait)
        {
            cout << " " << ait->name() << ": " << ait->value() << endl;
        }
        cout << endl;
// You are already in a loop for this node so no need for this
//      for(xml_node_iterator sit = node.begin(); sit != node.end(); ++sit)
//      {
//          getNodeInfo(*sit);
//      }

        // just use the iterator you are already looping over
        getNodeInfo(*it);
    }
}

Finally your XML data is not well formed. It needs an all embracing tag like this:

<?xml version="1.0" encoding="UTF-8"?>
<HOUSES>
    <WATSON att="att1">
        <PHILIPS> 125 </PHILIPS>
        <PEREZ> 254 </PEREZ>
        <SANTOS> 222 </SANTOS>
    </WATSON>
    <PHILIPS>
        <CENTER> 121 </CENTER>
        <WATSON> 125 </WATSON>
        <SANTOS> 55 </SANTOS>
    </PHILIPS>
    <PEREZ>
        <WATSON> 254 </WATSON>
        <CENTER> 110 </CENTER>
    </PEREZ>
</HOUSES>

Hope that helps.

Galik
  • 47,303
  • 4
  • 80
  • 117
  • Note: pugixml does not enforce the "single document element" rule for practical concerns (too many documents break that). Now that there is parse_fragment this may happen in 2.0, who knows. – zeuxcg Nov 11 '14 at 21:26
  • Thank you so much. This helped a lot, really! I have two questions about the xml file: What is "att="att1"? And the function getNodeInfo() will read everything now with this new file? :) – I love programming with coffee Nov 12 '14 at 01:45
  • @Iloveprogrammingwithcoffee I added `"att="att1"` to I could test if your code to print out the attributes was working. And yes, `getNodeInfo()` is recursive so it will visit every node. Actually it would now read everything *without* the `` tag because (as @zeuxcg said) pugixml is not very fussy. – Galik Nov 12 '14 at 01:58
  • Thanks a lot for your help. You really helped me a lot. Now it's working. I just changed the format to a graphml and it works much better with variables. (Y) – I love programming with coffee Nov 14 '14 at 03:59