tags:

views:

282

answers:

6

There are plenty of Libraries to parse XML, but it seems there aren't many good (?) ways to write XML in C++.

Libraries I've been using so far:

  • PugiXML: really lightweight, very straightforwarded API, but it seems to lack a way to write XML (Or I haven't found it yet)
  • RapidXML: I don't have much experience with RapidXML; But it does look nice.
  • TinyXML: I find it odd that the STL TinyXML needs to be explicitly "enabled" in TinyXML - I mean, if your compiler doesn't support the STL, get a better one!

Anyway, to make my point clear, I have written a PHP Script that does what I plan to do in C++: http://codepad.org/RyhQSgcm

I really appreciate any help!

+3  A: 

Xerces DOM Parser

Xerces-C++ is a validating XML parser written in a portable subset of C++. Xerces-C++ makes it easy to give your application the ability to read and write XML data. A shared library is provided for parsing, generating, manipulating, and validating XML documents using the DOM, SAX, and SAX2 APIs. For an introduction to programming with Xerces-C++ refer to the Programming Guide.

The POCO project also has an XMLWriter that will allow you to generate XML.

Of course there is always this existing StackOverflow post.

Romain Hippeau
Though if "lightweight" was part of the requirements (which it seems to be from the other examples of libraries nebukadnezzar has already tried) then Xerces is on the totally other end of *that* scale!
Dean Harding
@cedeka: Yes, even though I haven't explicitly added as requirement, a lightweight library is what I'm looking for.
nebukadnezzar
@codeka I think between the three options I mention this is covered.
Romain Hippeau
@nebukadnezzar the existing post to stackoverflow I mention also covers this. This is really a repeat question.
Romain Hippeau
@Romain Hippeau: I hate to admit it, but tinyxml++ seems to be the best solution here.
nebukadnezzar
@nebukadnezzar - Thanks for the vote.
Romain Hippeau
+2  A: 

It was already mentioned in the comments, but I'm going to mention TinyXML again. I've never had any problems with it in the ~7 years I've been using it.

The API is not really idiomatic C++ (I've never really bothered with the "ticpp" wrapper myself) but it works well, it's fast and it's easy enough to wrap it yourself if your really don't like the API.

Dean Harding
+2  A: 

I use std::ostream::operator() and a simple function that will quote a string if necessary. Taking time and memory to build a DOM when all you want to do is exhale existing data into XML seems to be taking the long way around...

Jon Watte
+3  A: 

If you're working in C++ you should consider ticpp again. It doesn't take much to get set up and outputs (simple) valid xml using the exact syntax you'd expect from anything that deals with streams.

This link shows how to use the library, and the included build notes are sufficient to get everything set up.

Ephphatha
Much thanks for the awesome link
nebukadnezzar
+1 : interesting link
neuro
A: 

Most people are going to hate this answer, but I'm in the habit of writing XML longhand (in C++ this would be using ostream) and using third party libraries for reading XML.

I have not yet had the case to read and modify XML.

Joshua
+1  A: 

Because you specifically mentioned lightweight, and I haven't seen it mentioned, I'll add Boost.PropertyTree. It uses RapidXML under the hood.

It doesn't do anything but parse elements, but sometimes that is enough. And honestly, XML schema verification, XPath, and co. deserve to be split into separate libraries. It probably wouldn't be hard to tie in the existing C++ amalgamations that provide this extra coverage.

Example XML file/string:

std::string xml_providers =
    "<question>"
    "   <title>What’s a good way to write XML in C++?</title>"
    "   <date>2010/6/6</date>"
    "</question>"
    "<providers>"
    "   <provider speed=\"1\">Boost.PropertyTree</provider>"
    "   <provider speed=\"6\">TinyXML++</provider>"
    "   <provider speed=\"3\">PugiXML</provider>"
    "   <provider speed=\"9001\">Xerxes</provider>"
    "   <provider speed=\"1\">RapidXML</provider>"
    "</providers>";

boost::property_tree would be used like so:

using boost::property_tree::xml_parser::read_xml;
using boost::property_tree::ptree;
using boost::gregorian::from_string;
using boost::gregorian::date;

ptree doc;
std::istringstream iss(xml_providers);
xml_parser::read_xml(iss, doc);

std::string title = doc.get<std::string>("question.title");
date when = from_string(doc.get<std::string>("question.date"));
ptree providers = doc.get_child("providers");
std::size_t size = std::distance(providers.begin(), providers.end());

std::cout << "Question: " << title << std::endl;
std::cout << "Asked on: " << when << std::endl;
std::cout << size << " suggested XML providers" << std::endl << std::endl;
std::cout << std::left << std::setw(25)
    << "Provider" << "Speed" << std::endl;

providers.sort(sort_by_speed);
std::for_each(providers.begin(), providers.end(), send_to_cout);

And the two helper functions:

auto sort_by_speed = [](ptree::value_type& a, ptree::value_type& b) -> bool {
    int a_speed = a.second.get<int>("<xmlattr>.speed");
    int b_speed = b.second.get<int>("<xmlattr>.speed");
    return a_speed < b_speed;
};
auto send_to_cout = [](ptree::value_type& provider) {
    std::cout << std::left << std::setw(25)
        << provider.second.get_value<std::string>()
        << provider.second.get<int>("<xmlattr>.speed") << std::endl;
};

Output:

Question: WhatÆs a good way to write XML in C++?
Asked on: 2010-Jun-06
5 suggested XML providers

Provider                 Speed
Boost.PropertyTree       1
RapidXML                 1
PugiXML                  3
TinyXML++                6
Xerxes                   9001

It's so easy that you don't even need to know XML!

(Ignore the speed ratings I attributed the libraries. I made them up.)

edit: property_tree supports exporting XML from a ptree object, of course. I wrote an example for reading XML because (1) it's the only usage I am familiar with, and (2) there are very few examples online.

dean
+1 for the coding effort :)
neuro
I still feel a little bad for posting off topic. I was trying to show how ptree works as a DOM-like container. Given the example, how to use it for writing should become immediately apparent if you are familiar with the STL.
dean
-1 as it wasn't the question how to parse XML, but how to write XML.
nebukadnezzar
Fair enough. But you have to realize property_tree is brand new. I doubt many are familiar with it. FWIW, you can add `write_xml("file.xml", doc)` at the end, and it will function exactly as XML+ostream.
dean