writing more complex than trivial xml with boost property tree
Asked Answered
M

2

7

UPD I've found answer to "formatting" issue here, so I remove this part of the question, please read updated question:

I need to write xml to file system on c++. I've learned this titorial. In the tutorial pretty simple xml is used. My xml is more complicated and I don't know how to modify the code to produce it. That's what I've code:

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

//<Root>
//  <Set Name="1">
//      <Field Name="Hello 1"/>
//      <Field Name="World 1"/>
//  </Set>
//  <Set Name="2">
//      <Field Name="Hello 2"/>
//      <Field Name="World 2"/>
//  </Set>
//</Root>

int main(int argc, char* argv[])
{
    using boost::property_tree::ptree;
    ptree pt;

    pt.put("Root.Set.Field", "Hello");
    pt.put("Root.Set.Field", "World");

    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("testXml.xml", pt, std::locale(), settings);
    return 0;
}

Output is:

<?xml version="1.0" encoding="utf-8"?>
<Root>
<Set>
    <Field>World</Field>
</Set>
</Root>

How can I modify my program to produce desired xml, in particular:

  • How to add multiple nods with the same name? Adding true like that pt.put("Root.Set.Field", "Hello", true); is compile time error
  • How to set xml attributes? (Name="Hello 1") According to doc It seems I should add them to "subkeys", but how?

upd i've tried that: pt.put("Root.Set.Field.xmlattr.Name", "Hello 1"); expecting to see that <Field Name="Hello 1"/> but still doesn't work. Waiting for someone who can share correct syntax.

upd2 bingo, this syntax works, i will continue try to print desired xml tomorrow. pt.put("Root.Set.Field.<xmlattr>.Name", "Hello 1");

Manvel answered 18/9, 2013 at 14:47 Comment(6)
https://mcmap.net/q/115727/-what-is-the-best-open-xml-parser-for-c-duplicateApollus
xerces.apache.org/xerces-cApollus
if I can do what I need to do using boost i would prefer stay with boost. I don't want to add extra frameworks just for configs parsing.Manvel
https://mcmap.net/q/121888/-using-boost-to-read-and-write-xml-filesApollus
If it is just for configs parsing then do you really need to control in detail how the data is stored in the config? Wouldn't you be happier operating at the level of the property_tree API and letting boost store it however it likes as an implementation detail?Apollus
@AdamBurry i can read example xml using property_tree. so I guess i can write it too. somehow. probably It's better to learn full property_tree API than trying to use only certain subset of it.Manvel
M
12

This answers the last question - how to use several nodes with the same name. Finally I wrote such program that solves the problem

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

//<Root>
//  <Set Name="1">
//      <Field Name="Hello 1"/>
//      <Field Name="World 1"/>
//  </Set>
//  <Set Name="2">
//      <Field Name="Hello 2"/>
//      <Field Name="World 2"/>
//  </Set>
//</Root>

int main(int argc, char* argv[])
{
    using boost::property_tree::ptree;
    ptree pt;

    boost::property_tree::ptree rootNode;
    boost::property_tree::ptree setNode1;
    boost::property_tree::ptree setNode2;
    boost::property_tree::ptree fieldNode1;
    boost::property_tree::ptree fieldNode2;
    boost::property_tree::ptree fieldNode3;
    boost::property_tree::ptree fieldNode4;

    fieldNode1.put("<xmlattr>.Name", "Hello 1");
    fieldNode2.put("<xmlattr>.Name", "World 1");
    fieldNode3.put("<xmlattr>.Name", "Hello 2");
    fieldNode4.put("<xmlattr>.Name", "World 2");

    setNode1.add_child("Field", fieldNode1);
    setNode1.add_child("Field", fieldNode2);
    setNode2.add_child("Field", fieldNode3);
    setNode2.add_child("Field", fieldNode4);

    setNode1.put("<xmlattr>.Name", "1");
    setNode2.put("<xmlattr>.Name", "2");

    rootNode.add_child("Set", setNode1);
    rootNode.add_child("Set", setNode2);
    pt.add_child("Root", rootNode);

    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("testXml.xml", pt, std::locale(), settings);
    return 0;
}

Output:

<?xml version="1.0" encoding="utf-8"?>
<Root>
<Set Name="1">
    <Field Name="Hello 1"/>
    <Field Name="World 1"/>
</Set>
<Set Name="2">
    <Field Name="Hello 2"/>
    <Field Name="World 2"/>
</Set>
</Root>
Manvel answered 19/9, 2013 at 6:50 Comment(0)
A
0

property_tree is not intended as a generic XML API. It is intended for application config settings. Think: Windows INI files, or C# .config files, or Java .properties files. If you try to treat it as an XML parser you are going to be unhappy.

What you should use instead depends on your requirements. xerces, for example is an enterprise-class library. You could use proprty_tree if you can be more flexible in the structure of the data. There are many other choices available.

Apollus answered 18/9, 2013 at 14:59 Comment(2)
what should I use for xml writing and parsing on c++, then?Manvel
It is fair to note why we should expect that property_tree does not look like a conventional XML API, but that is all the more reason to explain how it is different. After all, it is able to read, modify and write XML documents in their entirety.Telephonist

© 2022 - 2024 — McMap. All rights reserved.