Fandom

Urho3D Wiki

XML

69pages on
this wiki
Add New Page
Comments0 Share

Urho3D uses PugiXML (http://pugixml.org/) and offers wrapping objects for that. I used PugiXML here directly because I used it before and the interface is already quite good and is relatively good documented. Maybe Urho's wrapper has some advantages, maybe not.

Parsing a XML file like this (a map file for USP):

<xml>
<static_model name="Data/Models/level_1" pos_x="0" pos_y="0" pos_z="-10" />
<player pos_x="4" pos_y="10" pos_z="-5" />
<flag pos_x="20.35" pos_y="14" pos_z="-47.6" />
<flag pos_x="-9.9" pos_y="14" pos_z="-47.7" />
<torch pos_x="-244" pos_y="36.2" pos_z="-104" />
<torch pos_x="-199" pos_y="28" pos_z="-138" />
<sound name="Music/Drums of the Deep.ogg" />
</xml>

Can be done like this:

#include <Urho3D/ThirdParty/PugiXml/pugixml.hpp>
...

// loads a level, the given filename could be "maps/level_1.xml"
level::level(std::string level_filename)
{ // make an xml document object
pugi::xml_document doc; // load a file (here a name is being generated)
pugi::xml_parse_result result=doc.load_file(("Data/"+level_filename).c_str()); // report an error if something did go wrong with loading
if(!result)
{
std::cout<<"XML parsed with errors, attr value: ["<<doc.child("node").attribute("attr").value()<<"]\n";
std::cout<<"Error description: "<<result.description()<<"\n";
std::cout<<"Error offset: "<<result.offset<<" (error at [..."<<(result.offset)<<"]\n\n";
}
// iterate over all elements at the root of the document // (the highest elements in the XML tree)
for(pugi::xml_node_iterator it=doc.children().begin(); it!=doc.children().end();it++) { // get the current node we are iterating over and iterate over all of // its children pugi::xml_node& c=*it;
for(pugi::xml_node_iterator it=c.children().begin(); it!=c.children().end();it++) { // get again a node, which is the child of the other one pugi::xml_node& child=*it;
// get its name and compare it to various values
std::string name(child.name()); if(name=="flag")
{
float pos_x=0;
float pos_y=0;
float pos_z=0;
// iterate over the attributes of that node (like the position // values in the XML example document at the top)
for(pugi::xml_attribute_iterator it=child.attributes().begin(); it!=child.attributes().end();it++) { // get again the attribute and compare its name and fill // variables with the attributes values pugi::xml_attribute& attr=*it;
if(std::string(attr.name())=="pos_x")
pos_x=std::stof(std::string(attr.value()));
else if(std::string(attr.name())=="pos_y")
pos_y=std::stof(std::string(attr.value()));
else if(std::string(attr.name())=="pos_z")
pos_z=std::stof(std::string(attr.value()));
} // use the variables we filled to fill a vector with the read // coordinated. flag_positions is a std::vector<Urho3D::Vector3>
flag_positions.emplace_back(pos_x,pos_y,pos_z);
} else if(name=="sound")
{ // sound_name is a Urho3D::String
for(pugi::xml_attribute_iterator it=child.attributes().begin(); it!=child.attributes().end();it++) { pugi::xml_attribute& attr=*it;
if(std::string(attr.name())=="name")
sound_name=attr.value(); }
} ...
}
}
}

Note: std::stof converts a std::string to a float, there is also stoi for string -> int.

Handy Print Function Edit

This recursive function uses PugiXML to print everything in an XML file in a nice tree-ish view with indentation:

void xml_print(const pugi::xml_node& n,int depth)
{
    std::string name(n.name());
    if(name!="")
    {
        for(int i=0;i<depth;i++)
            std::cout<<"  ";
        std::cout<<"name: "<<name<<endl;
    }

    std::string value(n.value());
    if(value!="")
    {
        for(int i=0;i<depth;i++)
            std::cout<<"  ";
        std::cout<<"value: "<<value<<endl;
    }

    for(pugi::xml_attribute& attr:n.attributes())
    {
        for(int i=0;i<depth;i++)
            std::cout<<"  ";
        std::cout<<"attribute '"<<attr.name()<<"': '"<<attr.value()<<"'"<<std::endl;
    }
    for(pugi::xml_node& child:n.children())
    {
        for(int i=0;i<depth;i++)
            std::cout<<"  ";
        std::cout<<"child"<<std::endl;
        xml_print(child,depth+1);
    }
}

Usage:

pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("test.xml");
if(!result)
{
    std::cout<<"XML parsed with errors, attr value: ["<<doc.child("node").attribute("attr").value()<<"]\n";
    std::cout<<"Error description: "<<result.description()<<"\n";
    std::cout<<"Error offset: "<<result.offset<<" (error at [..."<<(result.offset)<<"]\n\n";
    return;
}

for(auto& c:doc.children())
    xml_print(c,0);

Example output (from a totally different but more complex XML file):

name: rdf:RDF
attribute 'xmlns:foaf': 'http://xmlns.com/foaf/0.1/'
attribute 'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
attribute 'xmlns:ussec': 'http://www.rdfabout.com/rdf/schema/ussec/'
attribute 'xmlns:corp': 'http://xmlns.com/foaf/corp#'
child
  name: corp:Company
  attribute 'rdf:about': 'http://www.rdfabout.com/rdf/usgov/sec/id/cik0000037996'
  child
    name: ussec:tradingSymbol
    child
      value: F
  child
    name: foaf:name
    child
      value: FORD MOTOR CO
  child
    name: ussec:tenPercentOwnerOf
    attribute 'rdf:resource': 'http://www.rdfabout.com/rdf/usgov/sec/id/cik0001075056'
    attribute 'foaf:name': 'VASTERA INC'
  child
    name: ussec:cik
    child
      value: 0000037996

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.