任意xml的序列化和反序列化

我用递归的方法,实现了任意xml数据反序列化到一个类中,然后在序列化出来。用来撸onvif协议,好用极了。
当然,有很多序列化的工具,比如boost的serial, cereal等,但是这些工具的共同缺点就是你需要事先知道节点是什么,有一个先知的前提。

当然用递归的方式的一个隐患就是栈空间溢出,要小心点。

//
// Created by yangkai on 12/18/17.
//

#ifndef ONVIF_XMLNODE_H
#define ONVIF_XMLNODE_H


#include 
#include 
#include 
#include 

class NodeInfo {
public:
    NodeInfo() {}

    ~NodeInfo() {}

public:
    std::string _name;
    std::map _attributes;
    std::string value;

    std::vector _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 
#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::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::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::iterator it = pnode->_child.begin();
         it != pnode->_child.end();
         ++it) {
        serial_xml_node(*it, doc, mount);
    }
}

你可能感兴趣的:(任意xml的序列化和反序列化)