我用递归的方法,实现了任意xml数据反序列化到一个类中,然后在序列化出来。用来撸onvif协议,好用极了。
当然,有很多序列化的工具,比如boost的serial, cereal等,但是这些工具的共同缺点就是你需要事先知道节点是什么,有一个先知的前提。
当然用递归的方式的一个隐患就是栈空间溢出,要小心点。
//
// Created by yangkai on 12/18/17.
//
#ifndef ONVIF_XMLNODE_H
#define ONVIF_XMLNODE_H
#include <string>
#include <map>
#include <vector>
#include <rapidxml.hpp>
class NodeInfo {
public:
NodeInfo() {}
~NodeInfo() {}
public:
std::string _name;
std::map<std::string, std::string> _attributes;
std::string value;
std::vector<NodeInfo *> _child;
};
void scan_xml_node(const rapidxml::xml_node<> *node, NodeInfo *pnode);
void free_node(NodeInfo *pnode);
void serial_xml_node(NodeInfo *pnode, rapidxml::xml_document<> &doc, rapidxml::xml_node<> *father);
#endif //ONVIF_XMLNODE_H
实现:
//
// Created by yangkai on 12/18/17.
//
#include <cstring>
#include "XmlNode.h"
void scan_xml_node(const rapidxml::xml_node<> *node, NodeInfo *pnode) {
if (NULL == node || NULL == pnode) {
return;
}
//name
pnode->_name = node->name();
//attribute
for (rapidxml::xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute()) {
pnode->_attributes.insert(std::make_pair(attr->name(), attr->value()));
}
//value
if (strlen(node->value()) > 0) { //no child node
pnode->value = node->value();
} else {
for (rapidxml::xml_node<> *n = node->first_node(); n; n = n->next_sibling()) {
NodeInfo *child = new NodeInfo();
pnode->_child.push_back(child);
scan_xml_node(n, child);
}
}
}
void free_node(NodeInfo *pnode) {
if (NULL == pnode) {
return;
}
if (pnode->_child.empty()) {
delete pnode;
pnode = NULL;
return;
}
if (pnode->_child.size() > 0) {
for (std::vector<NodeInfo *>::iterator it = pnode->_child.begin();
it != pnode->_child.end();
++it) {
NodeInfo *ptmp = *it;
free_node(ptmp);
}
}
delete pnode;
pnode = NULL;
}
void serial_xml_node(NodeInfo *pnode, rapidxml::xml_document<> &doc, rapidxml::xml_node<> *father) {
if (NULL == pnode) {
return;
}
rapidxml::xml_node<> *mount = doc.allocate_node(rapidxml::node_element, pnode->_name.c_str(),
pnode->value.empty() ? NULL : pnode->value.c_str());
for (std::map<std::string, std::string>::iterator it = pnode->_attributes.begin();
it != pnode->_attributes.end();
++it) {
mount->append_attribute(doc.allocate_attribute((it->first).c_str(), (it->second).c_str()));
}
if (NULL == father) {
doc.append_node(mount);
} else {
father->append_node(mount);
}
for (std::vector<NodeInfo *>::iterator it = pnode->_child.begin();
it != pnode->_child.end();
++it) {
serial_xml_node(*it, doc, mount);
}
}
网友评论