anamika email
anamika email

Reputation: 347

How to get xml file parsed using TinyXml2 in c++ program?

I am using TinyXml2 for the first time to get a xml file as follows:

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

So, how will i get this type of xml genrated from TinyXml2 in visual studio. I have searched on internet but they have shown examples realy lengthy and complex to understand. So, kindly suggest me simple piece of code in c++ using tiny xml which can full my purpose.

Upvotes: 0

Views: 794

Answers (3)

sehe
sehe

Reputation: 393979

Here's using Pugi XML. I was really hoping this would be more user-friendly.

Note I've since added a non-troll answer here, since I found the time to work with 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);
}

No Live Demo, since Coliru doesn't have PugiXML. It prints:

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

Upvotes: 1

sehe
sehe

Reputation: 393979

In the troll answer category:

Note I've since added a non-troll answer here, since I found the time to work with TinyXML

  1. Boost Property Tree

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

    Prints

    <?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>
    

Upvotes: 2

sehe
sehe

Reputation: 393979

Ok, because you were very patient, and because I wanted to try out TinyXml2 for the first time, here goes:

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

Prints

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

Upvotes: 0

Related Questions