如何在c ++程序中使用TinyXml2解析xml文件?

时间:2015-06-02 11:15:30

标签: c++ boost tinyxml2

我第一次使用TinyXml2来获取xml文件,如下所示:

<ORDER>
<ITEM>
<SN>132487A-J</SN>
<NAME>crank casing</NAME>
<Person age="12" passed="Yes">Alive</Person>
<QTY>1</QTY>
</ITEM>
</ORDER>

那么,我将如何在Visual Studio中从TinyXml2中获得这种类型的xml。我在互联网上搜索过,但他们已经展示了一些冗长而复杂的例子。所以,请使用tiny xml在c ++中建议一些简单的代码,这些代码可以满足我的目的。

3 个答案:

答案 0 :(得分:2)

在巨魔答案类别中:

  

注意我添加了非巨魔答案here,因为我找到了使用TinyXML的时间

  1. 提升属性树

    <强> Live On Coliru

    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/xml_parser.hpp>
    
    struct Person {
        int age;
        bool passed;
        enum Condition { Alive, Dead } condition;
    
        friend std::ostream& operator<<(std::ostream& os, Condition c) {
            switch (c) {
                case Alive : return os << "Alive";
                case Dead  : return os << "Dead";
            }
            throw "failure"; //TODO
        }
    };
    
    struct Order {
        struct Item {
            std::string serialnumber, name;
            Person person;
            int quantity;
        };
    
        std::vector<Item> items;
    };
    
    using Tree = boost::property_tree::ptree;
    
    Tree make_tree(Person const& p) {
        Tree pt;
        pt.put("<xmlattr>.age", p.age);
        pt.put("<xmlattr>.passed", p.passed?"Yes":"No");
        pt.put_value(p.condition);
    
        return pt;
    }
    
    Tree make_tree(Order::Item const& p) {
        Tree pt;
        pt.put("SN",     p.serialnumber);
        pt.put("NAME",   p.name);
        pt.put_child("Person", make_tree(p.person));
        pt.put("QTY",    p.quantity);
    
        return pt;
    }
    
    Tree make_tree(Order const& p) {
        Tree pt;
        Tree& order = pt.put_child("ORDER", {});
        for (auto& item : p.items)
            order.add_child("ITEM", make_tree(item));
    
        return pt;
    }
    
    #include <iostream>
    /*
     *  <ORDER>
     *    <ITEM>
     *      <SN>132487A-J</SN>
     *      <NAME>crank casing</NAME>
     *      <Person age="12" passed="Yes">Alive</Person>
     *      <QTY>1</QTY>
     *    </ITEM>
     *  </ORDER>
     *
     */
    
    int main() {
        Order const order {
            {
                Order::Item {
                    "132487A-J", "crank casing", 
                    Person { 12, true, Person::Alive },
                    1
                },
            }
        };
    
        using namespace boost::property_tree;
        auto settings = xml_parser::xml_writer_make_settings<std::string>(' ', 4, "utf-8");
        write_xml(std::cout, make_tree(order), settings);
    }
    

    打印

    <?xml version="1.0" encoding="utf-8"?>
    <ORDER>
        <ITEM>
            <SN>132487A-J</SN>
            <NAME>crank casing</NAME>
            <Person age="12" passed="Yes">Alive</Person>
            <QTY>1</QTY>
        </ITEM>
    </ORDER>
    

答案 1 :(得分:1)

这是使用Pugi XML。我真的希望这会更加用户友好。

  

注意我已经添加了一个非巨魔答案here,因为我找到了使用TinyXML的时间

#include <pugixml.hpp>
#include <vector>
#include <iostream>
#include <sstream>

struct Person {
    int age;
    bool passed;
    enum Condition { Alive, Dead } condition;

    friend std::ostream& operator<<(std::ostream& os, Condition c) {
        switch (c) {
            case Alive : return os << "Alive";
            case Dead  : return os << "Dead";
        }
        throw "failure"; //TODO
    }
};

struct Order {
    struct Item {
        std::string serialnumber, name;
        Person person;
        int quantity;
    };

    std::vector<Item> items;
};

using Tree = pugi::xml_node;

Tree make_tree(Person const& p, pugi::xml_node parent) {
    auto pt = parent.append_child("Person");

    pt.append_attribute("age").set_value(p.age);
    pt.append_attribute("passed").set_value(p.passed?"Yes":"No");
    std::ostringstream oss;
    oss << p.condition;
    pt.append_child(pugi::node_pcdata).set_value(oss.str().c_str());

    return pt;
}

Tree make_tree(Order::Item const& p, pugi::xml_node parent) {
    auto pt = parent.append_child("ITEM");
    pt.append_child("SN").append_child(pugi::node_pcdata).set_value(p.serialnumber.c_str());
    pt.append_child("NAME").append_child(pugi::node_pcdata).set_value(p.name.c_str());
    make_tree(p.person, pt).set_name("Person");
    pt.append_child("QTY").set_value(std::to_string(p.quantity).c_str());

    return pt;
}

Tree make_tree(Order const& p, pugi::xml_node parent) {
    auto pt = parent.append_child("ORDER");
    for (auto& item : p.items)
        make_tree(item, pt);

    return pt;
}

#include <iostream>
/*
 *  <ORDER>
 *    <ITEM>
 *      <SN>132487A-J</SN>
 *      <NAME>crank casing</NAME>
 *      <Person age="12" passed="Yes">Alive</Person>
 *      <QTY>1</QTY>
 *    </ITEM>
 *  </ORDER>
 *
 */

int main() {
    Order const order {
        {
            Order::Item {
                "132487A-J", "crank casing", 
                Person { 12, true, Person::Alive },
                1
            },
        }
    };

    pugi::xml_document doc;
    make_tree(order, doc.append_child("ORDER"))
        .print(std::cout);
}

没有现场演示,因为Coliru没有PugiXML。它打印:

<ORDER>
    <ITEM>
        <SN>132487A-J</SN>
        <NAME>crank casing</NAME>
        <Person age="12" passed="Yes">Alive</Person>
        <QTY />
    </ITEM>
</ORDER>

答案 2 :(得分:0)

好的,因为你非常有耐心,而且因为我想第一次试用TinyXml2,这里有:

#include <tinyxml2.h>
#include <vector>
#include <iostream>
#include <sstream>

struct Person {
    int age;
    bool passed;
    enum Condition { Alive, Dead } condition;

    friend std::ostream& operator<<(std::ostream& os, Condition c) {
        switch (c) {
            case Alive : return os << "Alive";
            case Dead  : return os << "Dead";
        }
        throw "failure"; //TODO
    }
};

struct Order {
    struct Item {
        std::string serialnumber, name;
        Person person;
        int quantity;
    };

    std::vector<Item> items;
};

using Tree = tinyxml2::XMLNode;
using Document = tinyxml2::XMLDocument;

Tree* make_tree(Person const& p, Document& doc) {
    auto pt = doc.NewElement("Person");

    pt->SetAttribute("age", p.age);
    pt->SetAttribute("passed", p.passed?"Yes":"No");
    std::ostringstream oss;
    oss << p.condition;
    pt->SetValue(oss.str().c_str());

    return pt;
}

Tree* make_tree(Order::Item const& p, Document& doc) {
    auto pt = doc.NewElement("ITEM");
    (pt->InsertEndChild(doc.NewElement("SN")))->InsertFirstChild(doc.NewText(p.serialnumber.c_str()));
    (pt->InsertEndChild(doc.NewElement("NAME")))->InsertFirstChild(doc.NewText(p.name.c_str()));
    pt->InsertEndChild(make_tree(p.person, doc));
    (pt->InsertEndChild(doc.NewElement("QTY")))->InsertFirstChild(doc.NewText(std::to_string(p.quantity).c_str()));

    return pt;
}

Tree* make_tree(Order const& p, Document& doc) {
    auto pt = doc.NewElement("ORDER");
    for (auto& item : p.items)
        pt->InsertEndChild(make_tree(item, doc));

    return pt;
}

#include <iostream>
/*
 *  <ORDER>
 *    <ITEM>
 *      <SN>132487A-J</SN>
 *      <NAME>crank casing</NAME>
 *      <Person age="12" passed="Yes">Alive</Person>
 *      <QTY>1</QTY>
 *    </ITEM>
 *  </ORDER>
 *
 */

int main() {
    Order const order {
        {
            Order::Item {
                "132487A-J", "crank casing", 
                Person { 12, true, Person::Alive },
                1
            },
        }
    };

    Document doc;
    doc.InsertFirstChild(make_tree(order, doc));

    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);

    std::cout << printer.CStr() << "\n";
}

打印

<ORDER>
    <ITEM>
        <SN>132487A-J</SN>
        <NAME>crank casing</NAME>
        <Alive age="12" passed="Yes"/>
        <QTY>1</QTY>
    </ITEM>
</ORDER>