TinyXML: basic file reading

Started by
1 comment, last by ninmonkeys 17 years, 12 months ago
I've been reading the TinyXml documentation, and examples, but I'm having trouble getting it to read the values of elements, and attributes. I'm trying to read the values and attributes of the children if item elements. What am I doing wrong? Here's my example todo xml file. If the way I structered it seems wrong, say something. (Wasn't really sure how to structure it)
<TodoList>
	<item group="group1" title="script">
		<date year="2006" month="04" day="17"/>
		<text>make some script
		</text>
	</item>

	<item group="misc" title="tinyxml">
		<date year="2006" month="04" day="23"/>
		<text>fix it
		</text>
	</item>

</TodoList>
My real code is a mess, so here's the psuedo code.
	//root of document, in this case I'm taking root of item elements
	itemRoot = document.root().child("todolist");
	
	//grab first item element
 	curElem = itemRoot.Child("item");	
 	
 	//iterate through all item elements
	foreach(curElem = curElem.NextSibling())
	{
		cout << "Item: " << title << endl;
		cout << "date: " year << month << day;
		cout << "text: " << text << endl;
		
	}
Here's my current code to read the file. It's a real mess.
	//Item: each child 'item' of root
	//block: item/string? table
	{		
		todo_list.clear();
		
		//get first 'item' element
		//pElem=hRoot.FirstChild( "item" ).FirstChild().Element();
		//pElem=hRoot.FirstChild( "item" ).FirstChild("text").Element();
		
		//iterate through all items
		for(pElem=hRoot.FirstChild("item").Element(); pElem;
  			pElem->NextSiblingElement()) {
  			
  			//read children 'date', and 'text'
  
     		//attributes of date
  			//const char* attrib = pElem->FirstChild("year")->Attribute();
  			//if(attrib) { cout << "item->year: attribute=" << attrib << endl; }
  			
  			//text value
  			TiXmlElement* pCur = 0;
  			pCur = hRoot.Element();
  			if(!pCur) break;
  			pCur = pCur->FirstChildElement("item");
  			if(!pCur) break;
  			pCur = pCur->FirstChildElement("date");
  			if(!pCur) break;
  			if(pCur->Attribute("day")) {
  				cout << "\tAttribute=" << pCur->Attribute("day") << endl;
  			}
  			
  			
		}
		
		/*
		//iterate through all 'item' elements
		for( pElem; pElem; pElem=pElem->NextSiblingElement())
  		{
  			//append text to vector
  			const char* pText = pElem->GetText();
  			if(pText) {
  				cout << "key=" << pElem->Value() << ", "
  					<< "item: text=" << pText << endl;
			}
	 
		}*/
		
	
	}//end block
The output I get is repeated forever. It doesn't look like an endless loop to me. Unless next sibling doesn't ever end returning valid elements?
[tab]Attribute=17
[tab]Attribute=17
[tab]Attribute=17
[tab]Attribute=17
...etc...
Advertisement
A stab in the dark, try changing:
for(pElem=hRoot.FirstChild("item").Element(); pElem;  			pElem->NextSiblingElement())


to

for(pElem=hRoot.FirstChild("item").Element(); pElem;  			pElem=pElem->NextSiblingElement())
That was it.

Incase it will help someone else, here's my code to read the above xml file. I'm not error checking everything, and if I could get the number of children I wouldn't need to use pElem just as a counter for "item"'s offset.
using namespace std;//! Date structure, member of TodoData, used for element 'item'->'date' attributesstruct Date {	Date() : year(0), month(0), day(0) {}	int year; //! year	int month;//! month	int day; //! day};//! holds data from an 'item' element in the todo listclass TodoData {	public:		std::string text; //!item text		std::string group;	//!item group name		std::string title;	//!item title		Date date;	//! Date of 'item'		TodoData() : text("no text"), group("no group"), title("no title") {}		//!prints data to stdout		void Print(void) {			cout << "\ttitle=" << title << endl				<< "\tgroup=" << group << endl				<< "\tdate=" << date.year << "/" << date.month << "/"    			<< date.day << endl				<< "\ttext=" << text << endl;		 	} 	private:};//! read the xml todo file into vector of TodoDatavoid xmlRead(std::string filename) {	TiXmlDocument doc(filename.c_str());	if(!doc.LoadFile()){  		cout << "Error: could not load file: " << filename << endl;   		return;	}		TiXmlElement* pElem;	//!current element	TiXmlElement* pChild;	//!current child of pElem	TiXmlHandle hDoc(&doc);	//!handle to xml document	TiXmlHandle hRoot(0); //! handle to root element 'TodoList'		vector<TodoData> todo_list; //! todo list, data of all 'item' elements in xml	int count=0;	//! item count, starts at 0. used for index of 'item' element		//get root element 'TodoList', set to hRoot	pElem = hDoc.FirstChildElement().Element();	if(!pElem) { cout << "no valid root! quit-ing function!" << endl; return; }	//debug: cout << "root: " << pElem->Value() << endl;	hRoot = TiXmlHandle(pElem);		//Item: each child element named 'item' of hRoot ('TodoList')	{//block: main loop (block not required)				todo_list.clear();//clear vector		count = 0;  		//element: 'item', get attributes 'group', 'title', then iterate			//through siblings of 'item'		for(pElem=hRoot.FirstChild("item").Element(); pElem;  			pElem = pElem->NextSiblingElement()) 	    { 	    	//todo: not right, since pElem isn't used, but works for now? 	    	TodoData cur; //current data in this 'item' element 	    	 	    	//get 'item' element 	    	pChild = hRoot.Child("item",count).Element(); 	    	//debug: cout << "count: " << count << endl; 	    	if(pChild) {  	    		//debug: cout << "\tpChild: ok" << endl; 	    	}else { 	    		cout << "\tpChild: invalid!" << endl;  			}  			//read element 'item' attributes  			cur.group = pChild->Attribute("group");  			cur.title = pChild->Attribute("title");  			/*debug:			cout << "\titem group=" << pChild->Attribute("group")				<< " title=" << pChild->Attribute("title") << endl; */				       		//get element 'date', child of 'item'  			TiXmlElement* pCur = pChild->FirstChildElement("date");  			//debug: cout << "\tpCur = pChild->FirstChildElement('date');" << endl;  			if(pCur) {  	    		//debug: cout << "\tpCur: ok" << endl; 	    	}else { 	    		cout << "\tpCur: invalid!" << endl;  			}  			//read attributes of element 'date'  			/* debug:  			cout << "\tyear=" << pCur->Attribute("year")  				<< " month=" << pCur->Attribute("month")				<< " day=" << pCur->Attribute("day") << endl; */									//read date attributes, ints   			pCur->Attribute("year",&cur.date.year);   			pCur->Attribute("month",&cur.date.month);   			pCur->Attribute("day",&cur.date.day);						//get element 'text', child of 'item'			pCur = pChild->FirstChildElement("text");			//debug: cout << "\tpCur = pChild->FirstChildElement('text');" << endl;			if(pCur) {  	    		//debug: cout << "\tpCur: ok" << endl; 	    	}else { 	    		cout << "\tpCur: invalid!" << endl;  			}  			  						//read element 'text' value  			const char* pText = pCur->GetText();  			if(pText) {  				/* debug:      				cout << "\ttext=";     				cout << pText << endl; */     				     			cur.text = pText;						        	}else{        		cout << "pText: invalid!" << endl;        	}  			  							//append current 'item' data to todo_list, and increment counter  			todo_list.push_back(cur); 	    	count++; 	    } 	     	    cout << "iterate through vector:" << endl; 	    //iterate through vector 	    count=0; 	    for(vector<TodoData>::iterator iter=todo_list.begin(); 	    	iter != todo_list.end(); iter++)       	{       		cout << count << ")" << endl;   			iter->Print();       		count++;   		}   		cout << count+1 << " items parsed." << endl;				}//end: block main loop (shouldn't be here, reminant from tut)			}//end: functionint main(int argc, char *argv[]) {    xmlRead("demo.todo.xml");    cout << "Done." << endl;  system("pause"); //remove #include <cstdio> and this line unless you want it  return 0;}

This topic is closed to new replies.

Advertisement