如何解决在 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 举报,一经查实,本站将立刻删除。