Sign in to follow this  
Xiachunyi

TinyXML: I do not have a clue

Recommended Posts

Hello, I have spent today and yesterday trying to get coax my application to read XML files utilizing TinyXML but currently having no luck. I simply do not know how to proceed invoking the parser to begin going through and extracting data. So far I have the following:
//~~~~~Load Data Attributes Files
    TiXmlDocument PlayerUnitAttrib("Data/Objects/PlayerUnits.xml");
    PlayerUnitAttrib.LoadFile();
    if(PlayerUnitAttrib.Error() && PlayerUnitAttrib.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE) 
    {
        MessageBox(hwnd, "XML Parser Error", "Could not load file: PlayerUnits.xml", MB_OK | MB_ICONEXCLAMATION);
        return false;
    }

//~~~~~Allocate and Parse Data into Application
    TiXmlHandle hPlayerUnitAttrib(&PlayerUnitAttrib);


I do not know how to go from there, say if I was reading from the text below:
...
<Body>
  <Unit ID="1">
    <Name>Xiachunyi</Name>
    <Data>2000</Data>
  </Unit>
</Body>
...
I have looked at the example(s) provided by TinyXML and Gamedev but it still confuses me. Can anyone explain to me or point me in another direction as to what I am to do to read from a parent, child, sibling, and attribute? Thank you.

Share this post


Link to post
Share on other sites

Maybe you'll find this code usefull, it's extracted from my game's sources.




// create new document
TiXmlDocument xmlDoc(levelName.c_str());

// error handling
if (!xmlDoc.LoadFile())
{
string tmp("Couldn't load level from file: ");
tmp += levelName;
tmp += ", reason: ";
tmp += xmlDoc.ErrorDesc();
logError2("Game", tmp.c_str());
xmlDoc.Clear();
return false;
}

// "Level" is the main, root tag of our file
TiXmlElement * root = xmlDoc.FirstChildElement("Level");

if (!root)
{
logError2(levelName.c_str(), "Not found root 'Level' tag.");
xmlDoc.Clear();
return false;
}


// iterate through all found "Entity" tags
for (const TiXmlElement * itor = _xmlStream->FirstChildElement("Entity"); itor; itor = itor->NextSiblingElement("Entity"))
{
// if tag has attribute which value equals "Platform", that is it looks like this:
// <Entity Type="Plarform">
if (!strcmp(itor->Attribute("Type"), "Platform"))
{
// create it
TPlatform * newPlatform = new TPlatform;

if (!newPlatform)
{
logError2("Game", "Critical: Couldn't allocate memory for new Platform.")
continue;
}

if (!newPlatform->Create(itor)) // implementation of this function can be found later
return false;

platforms.push_back(newPlatform);
}
}

// ...


bool TPlatform :: Create(const TiXmlElement * _xmlStream)
{

// obtain pointer to "Shadow" tag, which is child node of _xmlStream, ie:
// <Entity Type="Platform">
// <Shadow>
const TiXmlElement * xmlShadowTag = _xmlStream->FirstChildElement("Shadow");

// if it's non zero, then use it, otherwise - we have error
if (xmlShadowTag)
{
// once again, obtain pointer to tag "Offset" which is child of "Shadow" tag:
// <Entity Type="Platform">
// <Shadow>
// <Offset>
const TiXmlElement * xmlOffsetTag = xmlShadowTag->FirstChildElement("Offset");

if (xmlOffsetTag)
{
shadowOffset.x = GetTagValueSlint(xmlOffsetTag, "x");
shadowOffset.y = GetTagValueSlint(xmlOffsetTag, "y");
hasShadow = true;
}

shadowTransparency = GetTagValueSlint(xmlShadowTag, "Transparency");

}



There are a lots of comments, so ideally you should be able to get a grasp of how to parse XMLs. One note though: I'm not using handles.

Other functions which I find handy. They can be used as a quick n' dirty method of obtaining value from tags:


// ------------------------------------------------- start GetTagValueTxt

const char * SC :: GetTagValueTxt(const TiXmlElement * _xmlStream, const char * _tagName)
{
const TiXmlElement * tag = _xmlStream->FirstChildElement(_tagName);

if (tag)
{
const TiXmlNode * node = tag->FirstChild();

if (node)
{
const TiXmlText * value = node->ToText();
if (value) return (value->Value());
else return 0;
} else return 0;
} else return 0;

}

// ------------------------------------------------- end GetTagValueTxt

// ------------------------------------------------- start GetTagValueTxt

const char * SC :: GetTagValueTxt(const TiXmlElement * _xmlStream)
{
if (_xmlStream)
{
const TiXmlNode * node = _xmlStream->FirstChild();

if (node)
{
const TiXmlText * value = node->ToText();
if (value) return (value->Value());
else return 0;

} else return 0;
}
else return 0;
}

// ------------------------------------------------- end GetTagValueTxt

// ------------------------------------------------- start GetTagValueSlint

SC :: slint SC :: GetTagValueSlint(const TiXmlElement * _xmlStream, const char * _tagName, slint _default)
{
const TiXmlElement * tag = _xmlStream->FirstChildElement(_tagName);

if (tag)
{
const TiXmlNode * node = tag->FirstChild();

if (node)
{
const TiXmlText * value = node->ToText();
if (value) return atoi(value->Value());
else return _default;
} else return _default;
} else return _default;
}

// ------------------------------------------------- end GetTagValueSlint

// ------------------------------------------------- start GetTagValueFloat

float SC :: GetTagValueFloat(const TiXmlElement * _xmlStream, const char * _tagName, float _default)
{
const TiXmlElement * tag = _xmlStream->FirstChildElement(_tagName);

if (tag)
{
const TiXmlNode * node = tag->FirstChild();

if (node)
{
const TiXmlText * value = node->ToText();
if (value) return atof(value->Value());
else return _default;
} else return _default;
} else return _default;
}

// ------------------------------------------------- end GetTagValueFloat



HTH :-)

Share this post


Link to post
Share on other sites
No prob :-)

One thing I forgot to add in previous mail is the documentation of functions:


//! From <_tagName> valueText </_tagName> returns valueText. _tagName is tag inside _xmlStream.
const char * GetTagValueTxt(const TiXmlElement * _xmlStream, const char * _tagName);

//! Directly from _xmlStream returns text value that is have, or 0 if it doesn't exist.
const char * GetTagValueTxt(const TiXmlElement * _xmlStream);


//! From <_tagName> valueSlint </_tagName> returns converted valueSlint.
//! \param _default will be returned if any error has occured.
slint GetTagValueSlint(const TiXmlElement * _xmlStream, const char * _tagName, slint _default = 0);


//! From <_tagName> valueFloat </_tagName> returns converted valueFloat.
//! \param _default will be returned if any error has occured.
float GetTagValueFloat(const TiXmlElement * _xmlStream, const char * _tagName, float _default = 0);


Share this post


Link to post
Share on other sites

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