1

I am using Rapidxml in c++ to read in a xml file

I have two questions based on the following example

<?xml version="1.0" encoding="utf-8"?>
<rootnode version="1.0" type="example">
  <childnode1 entry="1">
    <evendeepernode attr1="cat" attr2="dog"/>
    <evendeepernode attr1="lion" attr2="wolf"/>
  </childnode1>
  <childnode2 entry="1">
  </childnode2>
</rootnode>

1- if the number of same type of siblings(evendeepernode) is variable. How can I check for it?

2- if there are different siblings (e.g. childnode1 & childnode2 ) and there number is variable (e.g. there can be more than 1 childnode1's and/or there can be more than 1 childnode2's or one of them might not be there at all). how can I check for that?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
jj 1
  • 25
  • 8

1 Answers1

0

OK I have not compiled the code below but it should be accurate enough to modify it to your needs. It should at least illustrate the approach and the functions that you can use for your purposes. There may be better ways, but this will do what you need if you get no other replies.

For problems like 1- that you describe I use code similar to the following

xml_document<> doc;    
doc.parse<0>(xml_buffer);    // parse your string
xml_node<>* rootnode = doc.first_node("rootnode");  // Get first node
xml_node<>* childnode1 = rootnode->first_node("childnode1");     // childnode1

if (childnode1 != NULL) {
    // get first deeper node and loop over them all
    int number_of_siblings = 0;
    xml_node<>* deepernode = childnode1->first_node();
    while (deepernode != NULL) {
        // Do processing on this node

        // Your processing code here....

        // now get the next deepernode in this current level of nesting
        // pointer will be NULL when no more siblings 
        deepernode = deepernode->next_sibling();
        number_of_siblings++;
    }
    // Your xml had number_of_sibling nodes at this level
}

For your question 2- You can use the same kind of while loop to loop through the sibling nodes at the childnode1 level. If you need to check the name of the sibling you can use

 string strNodeName = "childnode2";
 if (current_node->name() == strNodeName) {
     // current node is called childnode2 - do your processing.
 }

if you dont need to examine node names, just use this to loop over all child nodes under rootnode

xml_document<> doc;    
doc.parse<0>(xml_buffer);    // parse your string
xml_node<>* rootnode = doc.first_node("rootnode");  // Get first node
xml_node<>* childnode = rootnode->first_node();     // get first childnode
int child_node_count = 0;
while (childnode != NULL) {
    // Do processing on this node

    // get sibling of current node (if there is one)    
    childnode = childnode->next_sibling();
    child_node_count++;
}
// child_node_count is now the number of child nodes under rootnode.
mathematician1975
  • 21,161
  • 6
  • 59
  • 101
  • Hey thanks a lot for the help. 1 more question if the data is stored in a file called example.xml. How would I open that file and define an input stream like a "cin" for C++ – jj 1 Aug 04 '12 at 14:38
  • Look into the iostream file opening objects like fstream – mathematician1975 Aug 04 '12 at 15:20
  • I am trying to something like this xml_document<> doc; ifstream myfile("map.osm"); doc.parse<0>(myfile); and receive the following error Multiple markers at this line - Invalid arguments ' Candidates are: void parse(char *) ' - Symbol 'parse' could not be resolved – jj 1 Aug 04 '12 at 15:57
  • The file size can vary from a few KB to a few Mega bytes if it is ipmortant – jj 1 Aug 04 '12 at 16:10
  • as far as i know, you can only parse char arrays using RapidXML. I think you would have to read your files into a large enough char array or string and then use that. One thing to be aware of with RapidXML is that the parsing modifies the string, so if you need to use that string after parsing, you should make a copy. I really dont know if it is possible to parse directly from file like you are trying to do. – mathematician1975 Aug 04 '12 at 16:38