zoukankan      html  css  js  c++  java
  • XML文件生成C++代码(基于rapidxml)

    简述

    XML文件生成C++代码(基于pugixml)中的功能一致,只是这里改用的rapidxml来实现。就不多说了,直接放代码。

    代码

    #include "rapidxml-1.13/rapidxml.hpp"
    #include "rapidxml-1.13/rapidxml_utils.hpp"
    #include "rapidxml-1.13/rapidxml_iterators.hpp"
    #include "rapidxml-1.13/rapidxml_print.hpp"
    
    
    #include <algorithm>
    #include <cstdio>
    
    // XML节点名称中可以包含C++变量名不支持的字符
    // 需要将其规范化,使之能够正常作为C++变量名
    std::string normalVarName(std::string s)
    {
        //    XML 元素必须遵循以下命名规则:
        //        名称可以含字母、数字以及其他的字符
        //        名称不能以数字或者标点符号开始
        //        名称不能以字符 “xml”(或者 XML、Xml)开始
        //        名称不能包含空格
        //    可使用任何名称,没有保留的字词。
        // 如果只需要C++编译通过,完全可以将s转换为base16表示的字符串即可
        // 这里我只对 : . , ; 做一下处理,其它的就先不管了
        for(std::size_t pos = s.find_first_of(":.,;");
            pos != std::string::npos; pos = s.find_first_of(":.,;",pos+1)){
            s[pos] = '_';
        }
        return s;
    }
    
    // 对于节点的值,它有可能包含需要转义的字符,需要进行转义(未考虑C++原始字面常量)
    std::string toEscape(const std::string& s)
    {
        std::string s2;
        s2.reserve(s.size());
        for(std::size_t i=0;i<s.size();++i){
            switch (s[i]) {
            case '"':
            case '\':
                s2.push_back('\');
                break;
            default:
                break;
            }
            s2.push_back(s[i]);
        }
        return s2;
    }
    
    bool TraversalXml(rapidxml::xml_node<char>& node,int level = 0)
    {
        std::string s(level*4,32);
        if(level == 0){ /*表明是root节点*/
            puts("rapidxml::xml_document<char> xmldocObject;
    "
                 "rapidxml::xml_document<char>* xmldoc = &xmldocObject;
    "
                 "{
    "
                 "    rapidxml::xml_node<char>* decl = 
    "
                 "        xmldoc->allocate_node(rapidxml::node_pi,
    "
                 "             xmldoc->allocate_string("xml version='1.0' encoding='utf-8'"));
    "
                 "    xmldoc->append_node(decl);
    "
                 "}");
            puts("{");
        }
        // 获取节点名称
        std::string nodeName(node.name(),node.name_size());
        std::string nodeValue(node.value(),node.value_size());
        std::string parentName;
        if(node.parent() == NULL || node.parent()->name_size() == 0){
            parentName = "xmldoc";
        } else {
            parentName = std::string(node.parent()->name(),node.parent()->name_size());;
        }
    
        // pugixml这里有点问题,不知道是不是bug(我对XML规范和pugixml都不是很熟)
        // 一个节点A没有子节点的时候,它也能获取到它的一个子节点,这个子节点的name是
        // 空的,value与节点A相同,其它的属性信息也是没有的。
        // 所以在这里一些地方写的会比较别扭
        // 这里使用rapidxml的时候也有这个问题,所以我觉得可能是对于没有子节点的的节点
        // 它的值就是它的子节点吧。这只是我的猜想,并未查阅相关规范。
    
    
        if(!nodeName.empty()){
            printf("%s{/*add %s*/
    ",s.c_str(),nodeName.c_str());
    
            // 输出添加子节点代码
            if(nodeValue.empty()){
                printf("%s    rapidxml::xml_node<char>* %s = xmldoc->allocate_node(
    "
                       "%s        rapidxml::node_element,"%s",NULL);
    ",
                       s.c_str(),normalVarName(nodeName).c_str(),
                       s.c_str(),nodeName.c_str());
            }else{
                printf("%s    rapidxml::xml_node<char>* %s = xmldoc->allocate_node(
    "
                       "%s        rapidxml::node_element,"%s","%s");
    ",
                       s.c_str(),normalVarName(nodeName).c_str(),
                       s.c_str(),nodeName.c_str(),toEscape(nodeValue).c_str());
            }
    
            // 输出添加子节点到父节点代码
            printf("%s    %s->append_node(%s);
    ",
                   s.c_str(),normalVarName(parentName).c_str(),
                   normalVarName(nodeName).c_str());
    
            // 逐个输出属性信息添加代码
            for(rapidxml::xml_attribute<char>* attr = node.first_attribute();
                attr != NULL; attr = attr->next_attribute()){
                // 输出属性信息添加代码
                printf("%s    %s->append_attribute(
    "
                       "%s        xmldoc->allocate_attribute("%s","%s"));
    ",
                       s.c_str(),normalVarName(nodeName).c_str(),
                       s.c_str(),attr->name(),attr->value());
            }
        }
        // 遍历子节点
        for(rapidxml::xml_node<char>* subnode = node.first_node();
            subnode != NULL;subnode = subnode->next_sibling()){
            TraversalXml(*subnode,level+1);
        }
        // 与前面匹配
        if(!nodeName.empty()){
            printf("%s}/*end %s*/
    
    ",s.c_str(),nodeName.c_str());
        }
        // 与前面匹配
        if(level == 0){
            puts("}");
        }
        return true;
    }
    
    
    int main(int argc,char** argv)
    {
        if(argc != 2){
            puts("Usage:....");
            return 0;
        }
        try{
            rapidxml::file<char> xmlfile(argv[1]);
            rapidxml::xml_document<char> doc;
            doc.parse<0>(xmlfile.data());
            TraversalXml(doc);
        }
        catch(std::exception& e){
            puts(e.what());
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    [linux1exe元旦特供]基于wine的IE6一键安装
    http://www.tianya.cn/publicforum/content/funinfo/1/1869814.shtml
    最全的design pattern 概述
    例解 autoconf 和 automake 生成 Makefile 文件
    根据条件分组SQL
    SQL Express自动备份
    通过asp.net 短信猫发短信
    EXT.NET GridPanel(按键事件带参的另一种写法)
    Asp.net操作IIS(调试通过)
    面向接口编程详解——编程实例(T2噬菌体)
  • 原文地址:https://www.cnblogs.com/oloroso/p/8532624.html
Copyright © 2011-2022 走看看