Volomike Volomike - 3 months ago 35
C++ Question

How To Iterate XML Nodes in C++ with the TinyXML2 Library

How does one iterate nodes in TinyXML2? I tried following the documentation but am not able to grasp this.

http://www.grinninglizard.com/tinyxml2docs/index.html

My XML is already loaded into

std::string
. Thus, the following compiles:

#include "tinyxml2.hpp"
// assume I have code here which reads my XML into std::string sXML
tinyxml2::XMLDocument doc;
doc.Parse( sXML.c_str() );


Now what do I do with
doc
to iterate the item list so that I can pull out the title and author fields inside into
std::string
variables?

Here's my XML sample:

<?xml version=“1.0” encoding=“utf-8”?>
<books>
<item>
<title>Letters to Gerhardt</title>
<author>Von Strudel, Jamath</author>
</item>
<item>
<title>Swiss Systemic Cleanliness Principles, The</title>
<author>Jöhansen, Jahnnes</author>
</item>
</books>


Was hoping for something simple like a C++
vector
of
item
and then perhaps a C++
map
inside where I can address it by
"title"
and
"author"
or
.title
or
.author
.

Answer
// PARSE BOOKS

#pragma once
#include <string>
#include <stdio.h>
#include <vector>
#include "tinyxml2.hpp"

struct myRec {
  std::string title;
  std::string author;
};

std::vector<myRec> recs;

tinyxml2::XMLDocument doc;
doc.Parse( sXML.c_str() );
tinyxml2::XMLElement* parent = doc.FirstChildElement("books");

tinyxml2::XMLElement *row = parent->FirstChildElement();
while (row != NULL) {
  tinyxml2::XMLElement *col = row->FirstChildElement();
  myRec rec;
  while (col != NULL) {
    std::string sKey;
    std::string sVal;
    char *sTemp1 = (char *)col->Value();
    if (sTemp1 != NULL) {
      sKey = static_cast<std::string>(sTemp1);
    } else {
      sKey = "";
    }
    char *sTemp2 = (char *)col->GetText();
    if (sTemp2 != NULL) {
      sVal = static_cast<std::string>(sTemp2);
    } else {
      sVal = "";
    }
    if (sKey == "title") {
      rec.title = sVal;
    }
    if (sKey == "author") {
      rec.author = sVal;
    }
    col = col->NextSiblingElement();
  } // end while col
  recs.push_back(rec);
  row = row->NextSiblingElement();
} // end while row
signed long nLen = recs.size();
if (nLen > 0) {
  --nLen;
  nLen = (nLen < 0) ? 0 : nLen;
  for (int i = 0; i <= nLen; i++) {
    std::string sTitle = recs[i].title;
    std::string sAuthor = recs[i].author;
    std::cout << sTitle << "\n" << sAuthor << "\n";
  }
} else {
  std::cout << "Empty rowset of books.\n";
}

Note, I'm fairly new to C++. If you know of a way to optimize this in less lines, I'd be thrilled to see it.