c++xmldictionaryvectortinyxml2

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.


Solution

  • // 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.