Reputation: 1061
my XML knowledge is enough to get by.
What I want to do is blindly parse an XML string and get all of the elements and attributes starting at the root. I can't use recursion like the example in the documentation and I can't seem to grasp how to do it with a loop. I know enough to get the root from the XML string and can loop through the string, but can't seem to get the attributes or text values.
I do not know any names of any tags and need to figure them out as I parse. Anyone have any idea how I start or an example?
Thanks
Here is the code I have so far for a XML string like this, works unless its nested elements like the location and country:
string strData = "<MyStuff mystring1=""111"" mystring2=""223"">\
<MYTAG1>0</MYTAG1>\
<MYTAG2>0</MYTAG3>\
<MYTAG4>0</MYTAG4>\
<location><country>GreatBritain</country></location>\
</MyStuff>";
void parseXmlString2( TiXmlNode* root )
{
TiXmlNode* child;
TiXmlElement* elem = (TiXmlElement*)root;
TiXmlAttribute* pAttrib = elem->FirstAttribute();
//This gets the root and its attributes.
while(pAttrib)
{
cout << "Value: " << pAttrib->Name() << ":" << pAttrib->Value() << endl;
pAttrib=pAttrib->Next();
}
//Now I want to parse up the rest.
//Does not work if nested such as <location><country>GreatBritain</country></location>
for( child = root->FirstChild(); child; child = child->NextSibling() )
{
//Test For child.
if(child->FirstChild())
{
//My helper fuct to tell type
//getType(child->FirstChild()->Type());
TiXmlNode* myChild;
for( myChild = child->FirstChild(); myChild; myChild = child->IterateChildren(child->FirstChild()))
{
cout << " " << myChild->Value() << endl;
}
}
}
}
Upvotes: 1
Views: 2454
Reputation: 1061
Ultimately this worked for me, thanks to everyone for the input:
for( child = root->FirstChild(); child; child = child->NextSibling() )
{
if(child->Type() == TiXmlNode::TINYXML_ELEMENT)
{
thevalue = child->Value();
}
//If this Node has children traverse them.
//and keep going for all.
if(child->FirstChild())
{
TiXmlNode* myChild = child->FirstChild();
while(myChild)
{
if(myChild->Type() == TiXmlNode::TINYXML_ELEMENT)
{
thevalue = child->Value();
}
if(myChild->Type() == TiXmlNode::TINYXML_TEXT)
{
thevalue= myChild->Value();
}
myChild = myChild->FirstChild();
}
}
}
Upvotes: 3
Reputation: 467
I don't know if I got you right. But if you already achieved looping through the XMLElements of your document without recursion then looping through the XMLAttributes should be easy.
Say you have your XMLElement* elem
you want to obtain the attributes from simply do
XMLAttribute* attrib;
for( attrib = elem->FirstAttribute(); attrib != NULL; attrib = attrib->Next() ) {
// do something
std::cout << attrib->Name() << " " << attrib->Value();
}
Just to see if TinyXML2 does everything right I wrote the following primitive, recursive function which prints out all elements and their attributes (without values):
void printAllChildren( XMLElement* parent, int recursionlvl ) {
std::stringstream indent("");
for( int i = 0; i <= recursionlvl; i++ ) {
indent << " ";
}
std::cout << "Element Name: " << indent.str() << parent->Name() << " ";
const XMLAttribute* attrib;
for( attrib = parent->FirstAttribute(); attrib != NULL; attrib = attrib->Next() ) {
std::cout << attrib->Name() << " ";
}
std::cout << std::endl;
XMLElement* childEl;
for( childEl = parent->FirstChildElement(); childEl != NULL; childEl = childEl->NextSiblingElement() ) {
printAllChildren( childEl, recursionlvl + 1 );
}
}
Hope that helps. Cheers.
EDIT: Without the applications actual output it's hard to guess where the error lies. But shouldn't it be
for( myChild = child->FirstChild(); myChild; myChild = child->IterateChildren( child ) )
in your most inner loop? (see a TinyXML Reference)
Upvotes: 0