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");

Community
  • 1
  • 1
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • http://stackoverflow.com/questions/170686/best-open-xml-parser-for-c – Adam Burry Sep 18 '13 at 15:05
  • http://xerces.apache.org/xerces-c/ – Adam Burry Sep 18 '13 at 15:06
  • 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. – Oleg Vazhnev Sep 18 '13 at 15:06
  • http://stackoverflow.com/questions/1042855/boost-and-xml-c – Adam Burry Sep 18 '13 at 15:09
  • 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? – Adam Burry Sep 18 '13 at 15:11
  • @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. – Oleg Vazhnev Sep 18 '13 at 15:55

2 Answers2

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>
Community
  • 1
  • 1
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
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.

Adam Burry
  • 1,904
  • 13
  • 20
  • what should I use for xml writing and parsing on c++, then? – Oleg Vazhnev Sep 18 '13 at 15:02
  • 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. – geo Feb 25 '22 at 11:33