2012-01-01 15 views
5

Ho il seguente file XML e voglio memorizzarlo usando le strutture sottostanti.Parse XML con albero delle proprietà boost

le struct dati:

struct transitions 
    { 
    string oldstate; 
    string event; 
    string newstate; 
    }; 

    struct XML_Diagram 
    { 
    string diag_name; 
    string diag_defaultstate; 
    list<string> diag_states; 
    list<string> diag_events; 
    list<transitions> diag_transitions; 
    }; 

il file xml:

<diagram> 
     <diagname>DiagaX</diagname> 
     <states> 
     <state>A</state> 
     .............  
     </states> 
     <events> 
      <event>ev1</event> 
      ................. 
     </events> 
     <defaultstate>A</defaultstate> 
     <transitions> 
      <transition> 
       <oldstate>A</oldstate> 
       <event>ev1</event> 
       <newstate>B</newstate> 
      </transition> 
      <transition> 
       <oldstate>B</oldstate> 
       <event>ev2</event> 
       <newstate>C</newstate> 
      </transition> 
      ......................... 
     </transitions> 
    </diagram> 

E 'chiaro a me come posso accedere alla diagram.states. posso farlo con il codice folowing:

using boost::property_tree::ptree; 
    ptree pt; 

    // Get diagram states 
    BOOST_FOREACH(ptree::value_type &v, pt.get_child("diagram.states")) 
    { 
     diag_states.push_back(v.second.data()); 
    } 

Quello che non mi è chiaro è come posso accedere ai dati da al diagram.transitions.transition livello?

Il mio problema è che non sono riuscito a trovare alcun esempio nella documentazione su come analizzare file xml più complessi con diversi livelli.

risposta

4

Questa funzione di utilità utile attraversa e pretty-stampa un intero albero di proprietà:

using boost::property_tree::ptree; 

std::string q(const std::string& s) { return "\"" + s + "\""; } 

void print_tree(const ptree& pt, int level) 
{ 
    const std::string sep(2 * level, ' '); 
    BOOST_FOREACH(const ptree::value_type &v, pt) { 
     std::cout 
      << sep 
      << q(v.first) << " : " << q(v.second.data()) << "\n"; 
     print_tree(v.second, level + 1); 
    } 
} 

void print_tree(const ptree& pt) { print_tree(pt, 0); } 

I valori v.second sono alberi stessi cui si può accedere con i soliti metodi get. Le transizioni può ad esempio essere letta e stampata in questo modo:

using std::string; 

void print_transitions(const ptree& pt) 
{ 
    BOOST_FOREACH(
     const ptree::value_type &v, 
     pt.get_child("diagram.transitions")) 
    { 
     const ptree& child = v.second; 
     std::cout 
      << "Event " 
      << child.get<string>("event") 
      << " in state " 
      << child.get<string>("oldstate") 
      << " leads to state " 
      << child.get<string>("newstate") 
      << "\n"; 
    } 
} 
4

Ecco un altro esempio di come stampare ptree con gli attributi:

namespace pt = boost::property_tree; 

// worker 
typedef std::pair<const pt::ptree&, unsigned> tree_printer; 

// empty ptree helper 
const pt::ptree& empty_ptree() 
{ 
    static pt::ptree t; 
    return t; 
} 


std::ostream& operator <<(std::ostream& os, const tree_printer& p) 
{ 
    const pt::ptree& tree = p.first; 

    if(tree.empty()) return os; 

    const std::string indent(p.second, ' '); 

    BOOST_FOREACH(const pt::ptree::value_type& v, tree) 
    { 
     const std::string& nodeName = v.first; 

     if(nodeName == "<xmlattr>") continue; 

     os << indent << nodeName; 
     const pt::ptree& attributes = 
      v.second.get_child("<xmlattr>", empty_ptree()); 

     if(!attributes.empty()) 
     { 
      os << " [ "; 
      BOOST_FOREACH(const pt::ptree::value_type& attr, attributes) 
      { 
       const std::string& attrName = attr.first; 
       const std::string& attrVal = attr.second.data(); 

       os << attrName << " = '" << attrVal << "'; "; 
      } 
      os << "]"; 
     } 
     os << "\n"; 

     const pt::ptree& childNode = v.second; 
     os << tree_printer(childNode, p.second + 1); 
    } 

    return os; 
} 


std::ostream& operator <<(std::ostream& os, const pt::ptree& tree) 
{ 
    os << tree_printer(tree, 0); 

    return os; 
} 

Spero che questo aiuti.

Problemi correlati