написание более сложного, чем тривиальный xml, с деревом свойств boost

UPD Я нашел ответ на проблему "форматирования" здесь, поэтому я удалите эту часть вопроса, прочитайте обновленный вопрос:

Мне нужно написать xml в файловую систему на С++. Я изучил этот учебник. В учебнике используется довольно простой xml. Мой xml сложнее, и я не знаю, как изменить код для его создания. Вот что у меня есть код:

#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;
}

Выход:

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

Как я могу изменить свою программу для создания желаемого xml, в частности:

  • Как добавить несколько узлов с одинаковым именем? Добавление true таким образом pt.put("Root.Set.Field", "Hello", true); является ошибкой времени компиляции
  • Как установить атрибуты xml? (Name="Hello 1") Согласно документу вроде бы надо добавить их в "подключи", но как?

upd Я пробовал это: pt.put("Root.Set.Field.xmlattr.Name", "Hello 1"); ожидал увидеть это <Field Name="Hello 1"/>, но все равно не работает. Жду кого-то, кто может поделиться правильным синтаксисом.

upd2 бинго, этот синтаксис работает, я продолжу завтра пытаться напечатать желаемый xml. pt.put("Root.Set.Field.<xmlattr>.Name", "Hello 1");


person Oleg Vazhnev    schedule 18.09.2013    source источник
comment
stackoverflow.com/questions/170686/best- open-xml-parser-for-c   -  person Adam Burry    schedule 18.09.2013
comment
xerces.apache.org/xerces-c   -  person Adam Burry    schedule 18.09.2013
comment
если я могу делать то, что мне нужно, используя boost, я бы предпочел остаться с boost. Я не хочу добавлять дополнительные фреймворки только для разбора конфигов.   -  person Oleg Vazhnev    schedule 18.09.2013
comment
stackoverflow.com/questions/1042855/boost-and-xml-c   -  person Adam Burry    schedule 18.09.2013
comment
Если это только для разбора конфигов, то вам действительно нужно детально контролировать, как данные хранятся в конфиге? Разве вы не были бы счастливее, работая на уровне API property_tree и позволяя boost хранить его, как ему нравится, как деталь реализации?   -  person Adam Burry    schedule 18.09.2013
comment
@AdamBurry я могу прочитать пример xml, используя property_tree. так что я думаю, я тоже могу написать это. как-то. вероятно, лучше изучить полный API property_tree, чем пытаться использовать только определенное его подмножество.   -  person Oleg Vazhnev    schedule 18.09.2013


Ответы (2)


Это отвечает на последний вопрос - как использовать несколько узлов с одинаковым именем. Наконец-то я написал такую ​​программу, которая решает проблему

#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;
}

Вывод:

<?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>
person Oleg Vazhnev    schedule 19.09.2013

property_tree не предназначен для использования в качестве универсального XML API. Он предназначен для настройки конфигурации приложения. Подумайте: файлы Windows INI, файлы C# .config или файлы Java .properties. Если вы попытаетесь рассматривать его как анализатор XML, вы будете несчастны.

Что вы должны использовать вместо этого, зависит от ваших требований. xerces, например, является библиотекой корпоративного класса. Вы можете использовать proprty_tree, если вы можете быть более гибкими в структуре данных. Есть много других доступных вариантов.

person Adam Burry    schedule 18.09.2013
comment
что мне тогда использовать для записи и разбора xml на С++? - person Oleg Vazhnev; 18.09.2013