max a
max a

Reputation: 1

rapidxml weird parsing for one specific node

I've been looking for hours a solution to my (simple ?) problem but I cannot find anyone who encountered this. I'm using latest version of rapidxml(1.13). I'm currently trying to create a tile-based engine and I need to read tmx file. I'm been using rapidxml for a while and so far everything was great. It was able to read every node perfectly and with an expected behavior. But I came across one node it has a problem with. This is my tmx file :

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.6.0" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="12" nextobjectid="1">
 <tileset firstgid="1" source="../../../Tile_engine/Tile_engine/sprite/[Base]BaseChip_pipo.tsx"/>
 <tileset firstgid="1065" source="../../../Tile_engine/Tile_engine/sprite/collision.tsx"/>
 <layer id="4" name="background" width="100" height="100">
  <properties>
   <property name="bg" type="bool" value="false"/>
  </properties>
  <data encoding="csv">
//I've removed the data for clearer view
</data>
 </layer>
 <layer id="6" name="object" width="100" height="100">
  <properties>
   <property name="isSolid" type="bool" value="true"/>
  </properties>
  <data encoding="csv">
//I've removed the data for clearer view
</data>
 </layer>
 <layer id="9" name="front" width="100" height="100">
  <properties>
   <property name="isSolid" type="bool" value="false"/>
  </properties>
  <data encoding="csv">
//I've removed the data for clearer view
</data>
 </layer>
 <layer id="11" name="collision" width="100" height="100">
  <data encoding="csv">
//I've removed the data for clearer view
</data>
 </layer>
</map>

In order to debug, I'm using a basic read with rapidxml :

 xml_document<> doc;
    xml_node<> * root_node;
    // Read the xml file into a vector
    ifstream theFile ("sprites/map_wtf.tmx");
    vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
    buffer.push_back('\0');
    // Parse the buffer using the xml file parsing library into doc
    doc.parse<0>(&buffer[0]);
    // Find our root node
    root_node = doc.first_node("map");

When I try to read (and count) the layer node for example :

int count_node(0);
    for(xml_node<> * child = root_node->first_node("layer"); child != nullptr; child = child->next_sibling())
        count_node++;
    cout    <<  count_node;

The output is correct and gives me 4. But when I try to read the tileset node, the output gives me 6.

So I've assumed the behavior is link to the /> at the end of the tileset node (<tileset firstgid="1" source="../../../Tile_engine/Tile_engine/sprite/[Base]BaseChip_pipo.tsx"/>).

Since the nested property node has the same pattern (<property name="bg" type="bool" value="false"/>), I've tried this code :

int count_node(0);
    for(xml_node<> * child = root_node->first_node("layer")->first_node("properties")->first_node("property"); child != nullptr; child = child->next_sibling())
        count_node++;
    cout    <<  count_node;

who gives me the correct output aka : 1.

I've tried different parsing options for the line doc.parse<0>(&buffer[0]) but nothing works. I've also read the content of the buffer during theses tests and it was correct. I must have the wrong way to read the file but I cannot understand why this script reads layer node and property node fine, but not the tileset ones.

Can anyone help me ? Thanks !

Upvotes: 0

Views: 101

Answers (1)

grek40
grek40

Reputation: 13438

The question is based on a misunderstanding about the result of

xml_node<> * child = root_node->first_node("layer");
child = child->next_sibling();

The child = child->next_sibling() returns the next node on the same level irregardless of the node name or any other constraint that was applied during the root_node->first_node("layer") selection.

However, the next_sibling signature is basically the same as the first_node signature, so it can be used to apply criteria to the next sibling node to be found.

So the (untested) approach would be like

int count_node(0);
for(xml_node<> * child = root_node->first_node("tileset"); child != nullptr; child = child->next_sibling("tileset"))
    count_node++;
cout << count_node;

Upvotes: 0

Related Questions