在 C++11 中使用 Rapidxml 将 xml 解析为 std::map 树

问题描述

我需要遍历结构与此类似的 XML 文件

  <Node A attr1="1">
    <Node B>
      <Node C attr1="1" attr2 = "2">
        <Node D attr1="1" attr2 = "2" attr3 = "3">
        </Node D>
      </Node C>
    </Node B>
  </Node A>

并构建地图结构。

我已经使用示例弄清楚了如何遍历 DOM,但是我无法弄清楚如何正确填充节点。每个节点类都可以将属性插入地图(我认为这部分有效)或可以插入新的子节点。但是,我无法弄清楚插入新子节点的最佳方法是填充它并返回到父节点。有人可以帮忙吗?

#include <cstddef>
#include <cassert>
// #define RAPIDXML_NO_STDLIB
// #define RAPIDXML_NO_EXCEPTIONS
#include "rapidxml.hpp"

#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include <cstdint>
#include <map>
#include <memory> // std::unique_ptr<>,std::make_unique()

// #if defined(RAPIDXML_NO_EXCEPTIONS)
// void rapidxml::parse_error_handler(const char* what,void* where) {
//     printf("Parse error(@%p): %s\n",where,what);
//     std::abort();
// }
// #endif

typedef std::map<std::string,std::string> Attribute;

struct Node
{
    public:
        //std::map<std::string,std::string>::iterator it_Attributes;
        std::map<std::string,Node>::iterator it_nodes;

        std::map<std::string,std::string> XML_Attributes;
        std::map<std::string,std::unique_ptr<Node>> XML_Nodes;
};
 

void walk(const rapidxml::xml_node<>* node,int indent,std::unique_ptr<Node>& parent)
{
    const std::string ind = std::string(indent * 4,' ');
    printf("%s",ind.c_str());

    parent->XML_Nodes[ind.c_str()] =  std::unique_ptr<Node>(new Node());

    const rapidxml::node_type t = node->type();
    switch (t)
    {
    case rapidxml::node_element:
    {
        //printf("<%.*s",node->name_size(),node->name());
        //printf("%.*s",node->name());

        
        for (const rapidxml::xml_attribute<>* a = node->first_attribute()
            ; a
            ; a = a->next_attribute()
            )
        {
            parent->XML_Attributes[a->name()] = a->value();
            //printf(" %.*s",a->name_size(),a->name());
            //printf("='%.*s'",a->value_size(),a->value());
        }
        //printf("\n");

        for (const rapidxml::xml_node<>* n = node->first_node()
            ; n
            ; n = n->next_sibling()
            )
        {

            walk(n,indent + 1,parent);
        }
        //printf("%s</%.*s>\n",ind.c_str(),node->name());
    }
    break;

    case rapidxml::node_data:
        //printf("DATA:[%.*s]\n",node->value_size(),node->value());
        break;

    default:
        //printf("NODE-TYPE:%d\n",t);
        break;
    }
}


void processXmlFile(const char* data)
{
    enum
    {
        PARSE_FLAGS = rapidxml::parse_non_destructive
    };

    // NOTE : There is a `const_cast<>`,but `rapidxml::parse_non_destructive`
    //        guarantees `data` is not overwritten.
    rapidxml::xml_document<> xmlDoc;

    std::unique_ptr<Node> master(new Node());

    xmlDoc.parse<PARSE_FLAGS>(const_cast<char*>(data));
    
    walk(xmlDoc.first_node(),master);
}


template<class String>
std::vector<char> loadFile(const String& filename)
{
    std::vector<char> file;
    if (std::ifstream is{ filename,is.binary | is.ate })
    {
        file.resize(static_cast<size_t>(is.tellg()));
        is.seekg(0);
        is.read(file.data(),file.size());
        file.push_back(0);
    }
    return file;
}


int main(int argc,const char* argv[])
{
    const auto args = std::vector<std::string>(argv + 1,argv + argc);
    for (const auto& arg : args)
    {
        const auto xmlFile = loadFile(arg);
        if (!xmlFile.empty())
        {
            const auto tmp = xmlFile;

            processXmlFile(xmlFile.data());
            

            
            // // check for const correctness
            // if (memcmp(xmlFile.data(),tmp.data(),tmp.size()) != 0)
            // {
            //     printf("ERROR: xmlFile is overwritten.\n");
            // }
        }
    }
}

编译使用:

sudo g++ -o main main.cpp rapidxml.hpp -I /home/user/cp_libs/tests/ -std=c++11

发现Rapidxml 标头http://rapidxml.sourceforge.net/

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...