使用 boost 属性树解析 XML

Posted

技术标签:

【中文标题】使用 boost 属性树解析 XML【英文标题】:Parse XML with boost property tree 【发布时间】:2012-01-01 18:07:50 【问题描述】:

我有以下 XML 文件,我想使用以下结构存储它。

数据结构:

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

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>

我很清楚如何访问 diagram.states 。 我可以用以下代码做到这一点:

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

我不清楚的是如何从 diagram.transitions.transition 级别访问数据?

我的问题是我在文档中找不到任何关于如何解析具有多个级别的复杂 xml 文件的示例。

【问题讨论】:

【参考方案1】:

这个有用的实用函数遍历并漂亮地打印整个属性树:

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

v.second 值本身就是树,可以使用通常的get 方法访问。过渡 例如可以像这样访问和打印:

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

【讨论】:

【参考方案2】:

这是另一个如何使用属性打印ptree 的示例:

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;

希望这会有所帮助。

【讨论】:

以上是关于使用 boost 属性树解析 XML的主要内容,如果未能解决你的问题,请参考以下文章

使用属性树在 boost 中解析 xml

Boost属性树xml解析No such node()

通过使用 boost 属性树解析 JSON 文件来访问布尔值

如果将任何注释附加到键值,Boost 属性树 ini 解析会出错

boost中的属性是如何解析的?肥皂xml解析?

使用boost解析xml