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) { 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.