17

I've used boost serialization but this doesn't appear to allow me to generate xml that conforms to a particular schema -- it seems it's purpose was to just to persist a class's state.

Platform: linux

What do you guys use to generate NOT parse xml?

So far I'm going down Foredecker's route of just generating it myself -- it's not a large document but I really shouldn't be having this much trouble finding a decent library to generate it correctly.

As for boost, the things that I would like to be able to do is set the node names, set attributes in my nodes, and get rid of all the extra crap that comes with it as I don't really care about having to put my document back into that class.

eyberg
  • 3,160
  • 5
  • 27
  • 43
  • I have used [libxml++](http://libxmlplusplus.sourceforge.net/) to geneate XML, but I can't guarantee it's the easiest way! :-) – activout.se Nov 19 '08 at 21:10

6 Answers6

51

I recently reviewed a bunch of XML libraries specifically for generating XML code.

Executive summary: I chose to go with TinyXML++.

TinyXML++ has decent C++ syntax, is built on the mature TinyXML C libraries, is free & open source (MIT license) and small. In short, it helps get the job done quickly. Here's a quick snippet:

Document doc;
Node* root(doc.InsertEndChild(Element("RootNode")));
Element measurements("measurements");
Element tbr("TotalBytesReceived",  12);
measurements.InsertEndChild(tbr);
root->InsertEndChild(measurements);

Which produces:

<RootNode>
    <measurements>
        <TotalBytesReceived>12</TotalBytesReceived>
    </measurements>
</RootNode>

I've been quite happy with it.

I reviewed many others; here's some of the better contenders:

Xerces: The king-daddy. Does everything (especially when combined with Xalan) but is heavyweight and forces memory management onto the user.

RapidXML: Great for parsing (it's an in-situ parser and is fast) but not good for generation since adding nodes to the DOM requires memory management.

Boost.XML (proposal): Looks great - powerful, excellent C++ syntax. However it hasn't yet gone through the review process, is unsupported and the interface may well change. Almost used it anyway. Looking forward to it's acceptance into Boost.

Libxml(++): Very good; powerful, decent syntax. But it's large-ish if all you're doing is generating XML and is tied to the glibmm library (for ustring). If we were only on Linux (like yourself?) I would seriously consider.

XiMOL: Unique stream-based library. This was a little too simplistic for our needs but for basic XML generation you may find it quite useful. The stream syntax is quite neat.

Hopefully there's something in there of some use!

Guillaume Vincent
  • 13,355
  • 13
  • 76
  • 103
MattyT
  • 6,531
  • 2
  • 20
  • 17
  • Looking at the TinyXML++ issues page, it appears that it has some memory leaks. Have you experienced that? – metal Mar 28 '11 at 15:47
  • @mlimber I use it fairly regularly and have not, but I only use it for relatively small documents – Jim Jeffries Aug 19 '11 at 10:35
  • 5
    Hm, looking at the innermost element I doubt that the output and the code match. :-) – Christoph Wurm May 25 '12 at 07:30
  • Just a small hint: after working with TinyXML, I discovered pugiXML. Memory is cruciaI for me, I'm parsing huge XML trees. Made a quick comparison with a 800MB XML file. TinyXML required 9.5GB (!) of ram to parse it, while pugiXML needed around 3.5GB. – Szak1 Sep 17 '18 at 16:51
13

Some may declare me an XML heretic - but one effective way is to just generate it with your favorite string output tools (print, output streams, etc) - this can go to a buffer or a file.

Once saved - you really should then validate with a schema before committing it our shipping it off.

For one of our projects we have a very simple set of templates for managing begin/end tags and attributes. These each have a stream output operator. This makes it very easy to generate the source XML and debug. This makes the structure of the XML generation code look very much like the XML itself.

One advantage of this is that you can generate large amounts of XML efficiently if streaming to a file. You will pay the validation costs later (presumably at a better time for an expensive operation).

The downside of this technique is that it is essentially output only. It is not suitable for creating then consuming XML dynamically.

Benoît
  • 16,798
  • 8
  • 46
  • 66
Foredecker
  • 7,395
  • 4
  • 29
  • 30
  • 1
    thanks a lot! I spent the last 2-3 hours scouring the web, newsgroups, irc, etc... and in the past 20 minutes I built a generator that does exactly what I need to do using this method -- it's not beautiful; needs work but it DOES WORK -- thnx! – eyberg Nov 19 '08 at 22:28
  • 5
    Yep, Heretic! ;) Seriously though, I'd advise against going this route - there are many libraries out there that will help and prevent you from making mistakes in your XML. – MattyT Nov 19 '08 at 23:03
  • Well, I have been generating my own XML for years without issue. Like Foredecker, our XML is relatively simple but, perhaps, more complicated than what he states. – Rob Oct 19 '10 at 11:21
  • 3
    I instinctively agree with this answer, except that you *will* likely end up needing to escape some things. " and & may be enough for most uses, but if your data is diverse enough you'll end up writing half a general XML output generator anyway... – Edmund Oct 19 '10 at 11:45
10

Boost.PropertyTree is a nice and straightforward way of generating XML - especially if you are already using Boost.

The following is a complete example program:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

using boost::property_tree::ptree;
using boost::property_tree::write_xml;
using boost::property_tree::xml_writer_settings;

int wmain(int argc, wchar_t* argv[]) {
    char* titles[] = {"And Then There Were None", "Android Games", "The Lord of the Rings"};

    ptree tree;
    tree.add("library.<xmlattr>.version", "1.0");
    for (int i = 0; i < 3; i++) {
        ptree& book = tree.add("library.books.book", "");
        book.add("title", titles[i]);
        book.add("<xmlattr>.id", i);
        book.add("pageCount", (i+1) * 234);
    }

    // Note that starting with Boost 1.56, the template argument must be std::string
    // instead of char
    write_xml("C:\\Users\\Daniel\\Desktop\\test.xml", tree,
        std::locale(),
        xml_writer_settings<char>(' ', 4));

    return 0;
}

The resulting XML looks like this:

<?xml version="1.0" encoding="utf-8"?>
<library version="1.0">
    <books>
        <book id="0">
            <title>And Then There Were None</title>
            <pageCount>234</pageCount>
        </book>
        <book id="1">
            <title>Android Games</title>
            <pageCount>468</pageCount>
        </book>
        <book id="2">
            <title>The Lord of the Rings</title>
            <pageCount>702</pageCount>
        </book>
    </books>
</library>

One thing that's particularly nice are the dot-separated paths that allow you to implicitly create all the nodes along the way. The documentation is rather meager, but together with ptree.hpp should give you an idea of how it works.

Daniel Wolf
  • 12,855
  • 13
  • 54
  • 80
0

Which platform? MSXML is an option on Windows. CMarkup is another good choice. If .NET is an option, it has excellent XML support.

Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
  • CMarkup also works without .Net You can build it to use std::string or MFC CString. It does build the entire doc in memory if that is an issue – Martin Beckett Sep 10 '09 at 03:53
0

I haven't actually tried boost serialization to do this, but as I understand it, if you very carefully pick your options, you can set lots of different options in the schema (such as preventing pointer flyweighting and setting the element names for certain types)

coppro
  • 14,338
  • 5
  • 58
  • 73
0

i use tinyXml++ and it makes it very easy to create xml as posted above. It will also save it to a file in one command but i cant find out how to save it to a buffer.

Lodle
  • 31,277
  • 19
  • 64
  • 91