1

I am trying to figure out a way to load the text from an XML document I have created using TinyXML2. Here is the entire document.

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="15" height="13" tilewidth="32" tileheight="32">
 <tileset firstgid="1" name="Background" tilewidth="32" tileheight="32">
  <image source="background.png" width="64" height="32"/>
 </tileset>
 <tileset firstgid="3" name="Block" tilewidth="32" tileheight="32">
  <image source="block.png" width="32" height="32"/>
 </tileset>
 <layer name="Background" width="15" height="13">
  <data encoding="base64">
   AgAAAAIAAAACAAAA...
  </data>
 </layer>
 <layer name="Block" width="15" height="13">
  <data encoding="base64">
   AwAAAAMAAAADAAAAAwAAAAM...
  </data>
 </layer>
</map>

Basically, I want to copy the text from <data> into a string called background only if the layer name is "Background".

I have gotten the other variables like so:

// Get the basic information about the level
version = doc.FirstChildElement("map")->FloatAttribute("version");
orientation = doc.FirstChildElement("map")->Attribute("orientation");
mapWidth = doc.FirstChildElement("map")->IntAttribute("width");
mapHeight = doc.FirstChildElement("map")->IntAttribute("height");

That works great because I know the element name and the attribute name. Is there a way to say get the doc.FirstChildElement("map")->FirstChildElement("layer") and if it == "Background", get the text.

How would I accomplish this?

manlio
  • 18,345
  • 14
  • 76
  • 126
Pladnius Brooks
  • 1,248
  • 3
  • 19
  • 36

3 Answers3

3

I know this thread is quite old, but just in case someone perusing the internet might stumble upon this question as I have, I wish to point out that Xanx's answer can be simplified slightly.

In tinyxml2.h it says that for the function const char* Attribute( const char* name, const char* value=0 ) const, if the value parameter is not null, then the function only returns if value and name match. According to the comments in the file this:

if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();

can be written like this:

if ( ele->Attribute( "foo" ) ) {
    if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
}

So the code Xanx provided can be rewritten like this:

XMLElement * node =  doc.FirstChildElement("map")->FirstChildElement("layer");
std::string value;

if (node->Attribute("name", "Background")) // no need for strcmp()
{
   value = node->FirtChildElement("data")->GetText();
}

A minor change, yes, but something I wanted to add.

rcplusplus
  • 2,767
  • 5
  • 29
  • 43
1

I advice you to do something like this:

XMLElement * node =  doc.FirstChildElement("map")->FirstChildElement("layer");
std::string value;

// Get the Data element's text, if its a background:
if (strcmp(node->Attribute("name"), "Background") == 0)
{
   value = node->FirtChildElement("data")->GetText();
}
Xanx
  • 11
  • 1
1
auto bgData = text (find_element (doc, "map/layer[@name='Background']/data"));

Using tinyxml2 extension (#include <tixml2ex.h>). N.B. should really be wrapped in a try/catch block. Work in progress and documentation is incomplete (can deduce from the test example until it's ready).

I'll mention in passing that the other two answers only work properly when the desired <layer> element appears first.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
stanthomas
  • 1,141
  • 10
  • 9