Sign in to follow this  

TinyXML C++ From XML to variables?

This topic is 2962 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, After searching and trying a lot with tinyxml, I was wondering if its possible to read xml into cpp variables. For example:
  
<?xml version="1.0" ?> 
  <test>
  <x>5</x> 
  <y>3</y> 
  <w>1</w> 
  <h>0</h> 
  </test>
Loading that xml file in a way that somehow allows:
 cout << x; 
With the outcome being: 5 Is that possible? and if so, could someone please give me a simple example?

Share this post


Link to post
Share on other sites
C++ does not, to my knowledge, support reflection, so that's not possible. To clarify, it's not afaik possible in c++ to add members to a class after it is compiled, nor is it possible to determine the name of an appropriate member variable based on a string. It's possible to do those things in a language like Java, but even then, reflection is comparatively slow and there's no real case for making use of it here. Instead, you should parse the XML, find the element/attribute you want, and use a method like TiXmlElement::QueryIntAttribute() or TiXmlElement::GetText() to assign to the appropriate variable. Try the tutorial and scroll down to "XML to/from C++ objects".

Share this post


Link to post
Share on other sites
Just in addition to lightbringer's reply, this is an example of how you can use TinyXml to parse your .xml file:

#include "tinyxml/tinyxml.h"

#include <cassert>
#include <iostream>
#include <ostream>
#include <sstream>

void Process(const TiXmlElement* element)
{
assert(element);
assert(element->Value());
assert(element->GetText());

// convert the element's text to an int
// (even better: use boost::lexical_cast)
std::istringstream stream(element->GetText());
int n;
if (stream >> n)
{
std::cout << element->Value() << ": " << n << std::endl;
}
else
{
// FIXME: signal the error somehow (e.g., by throwing an exception)
}
}

int main()
{
TiXmlDocument doc("test.xml");
if (doc.LoadFile())
{
TiXmlElement* root = doc.FirstChildElement("test");
assert(root);

for (TiXmlElement* child = root->FirstChildElement(); child; child = child->NextSiblingElement())
{
// do what you want with the element; in this case and as a simple example,
// we try to convert its text to an int and display it on the standard output
Process(child);
}

// alternatively, ...
Process(root->FirstChildElement("x"));
Process(root->FirstChildElement("y"));
Process(root->FirstChildElement("w"));
Process(root->FirstChildElement("h"));
}
}


[Edited by - Metsan on November 8, 2009 10:49:23 AM]

Share this post


Link to post
Share on other sites
You could (ab)use the preprocessor:


template <typename T>
void ReadVar(const TiXmlElement *elem, const char *name, T& val) {
TiXmlElement *varElem = elem->FirstChildElement(name);
if(!varElem)
throw std::runtime_error("Value not found for " + name);
DoReadVar(varElem->GetText(), name, val);
}

template <typename T>
void DoReadVar(const char *valText, const char *name, T& val) {
std::istringstream valStream(valText);
if(!(valStream >> val))
throw std::runtime_error("Bad value format" + name);
}

void DoReadVar(const char *valText, const char *, std::string& val) {
val = valText;
}

#define READ_VAR(elem, val) ReadVar(elem, #val, val)

int main() {
TiXmlElement *varsElem = // ...

int numDucks;
float duckHeight;
bool ducksAreManeating;
std::string duckLeaderName;

try {
READ_VAR(varsElem, numDucks);
READ_VAR(varsElem, duckHeight);
READ_VAR(varsElem, ducksAreManeating);
READ_VAR(varsElem, duckLeaderName);
} catch (const std::runtime_error& e) {
// ...
}
}

Share this post


Link to post
Share on other sites

This topic is 2962 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this