65.9K
CodeProject is changing. Read more.
Home

Hints for Using Poco Project XML Configuration

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2 votes)

Sep 8, 2014

CPOL

1 min read

viewsIcon

12900

The Poco XML Configuration has thrown up a number of (unanswered) questions across the inter-webs. This tip is intended to answer the commonest of them all, how to read multiple tags within an XML container tag

Introduction

When using Poco's XML Configuration, some things are obvious and we don't see questions asked because the documentation is adequate. However, going to the next logical step is not often obvious resulting in many unanswered FAQs around web forums. In this post, we explore that next step and provide workable solutions as a template going forward.

Background

The Poco documentation provides an obvious solution to the following problem.

Given this XML in file hello.xml:

<root>
  <headers>
    <header>Hello World</header>
  </headers>
</root>

Then the Poco XML Configuration can be used thus:

#include <string>
#include <Poco/AutoPtr.h>
#include <Poco/Util/XMLConfiguration.h>

using namespace std;
using namespace Poco;
using namespace Poco::Util

int main(int argc, char*argv[]) {

    AutoPtr apXmlConf(new XMLConfiuration("hello.xml"));
    string header = apXmlConf->getString("headers.header");
    cout << header << endl;
    return 0;
}

So far so good. The Poco documentation explains this well. However, the problem arises when the XML looks like this:

<root>
    <headers>
        <header>Hello</header>
        <header>World</header>
    </headers>
</root>

Iterating over multiple rows of data using XMLConfiguration is generally the FAQ seen most often.

One solution is as follows:

#include <string>
#include <sstream>
#include <Poco/Exception.h>
#include <Poco/AutoPtr.h>
#include <Poco/Util/XMLConfiguration.h>

using namespace std;
using namespace Poco;
using namespace Poco::Util

int main(int argc, char*argv[]) {

    int counter = 0;
    AutoPtr apXmlConf(new XMLConfiuration("hello.xml"));
    try {
        while(1) { // Loop breaks by Poco exception
            stringstream tag;
            tag << "headers.header[" << counter++ << "]";
            string header = apXmlConf->getString(tag.str());
            cout << header << " ";
        }
    } catch(NotFoundException& e) { (void)e; }
    cout << endl;
    return 0;
}

Points of Interest

Essentially the XMLConfiguration::get* functions require a string and most devs use a string literal. However, when iterating multiple contained tags, you need to provide an index so one needs to construct it as it loops over the data. On this occasion, I used a std::stringstream.

Note, in the example, the while loop goes forever and is broken by a Poco::NotFoundException so you will need to actually wrap the loop in a try/catch and expect that to break the while loop.