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;\n"
"rapidxml::xml_document<char>* xmldoc = &xmldocObject;\n"
"{\n"
" rapidxml::xml_node<char>* decl = \n"
" xmldoc->allocate_node(rapidxml::node_pi,\n"
" xmldoc->allocate_string(\"xml version='1.0' encoding='utf-8'\"));\n"
" xmldoc->append_node(decl);\n"
"}");
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*/\n",s.c_str(),nodeName.c_str());
// 输出添加子节点代码
if(nodeValue.empty()){
printf("%s rapidxml::xml_node<char>* %s = xmldoc->allocate_node(\n"
"%s rapidxml::node_element,\"%s\",NULL);\n",
s.c_str(),normalVarName(nodeName).c_str(),
s.c_str(),nodeName.c_str());
}else{
printf("%s rapidxml::xml_node<char>* %s = xmldoc->allocate_node(\n"
"%s rapidxml::node_element,\"%s\",\"%s\");\n",
s.c_str(),normalVarName(nodeName).c_str(),
s.c_str(),nodeName.c_str(),toEscape(nodeValue).c_str());
}
// 输出添加子节点到父节点代码
printf("%s %s->append_node(%s);\n",
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(\n"
"%s xmldoc->allocate_attribute(\"%s\",\"%s\"));\n",
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*/\n\n",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;
}
XML文件生成C++代码(基于rapidxml)的更多相关文章
- XML文件生成C++代码(基于pugixml)
简述 在一个项目中需要用到XML的解析和生成,知乎上有人推荐rapidxml和pugixml等库.RapidXML一看库还比较大,就先研究一下pugixml了. 因为对解析XML的需求不大(都是一些很 ...
- 使用XML文件和Java代码控制UI界面
Android推荐使用XML文件设置UI界面,然后用Java代码控制逻辑部分,这体现了MVC思想. MVC全名是Model View Controller,是模型(model)-视图(view)-控制 ...
- Android color(颜色) 在XML文件和java代码中
Android color(颜色) 在XML文件和java代码中,有需要的朋友可以参考下. 1.使用Color类的常量,如: int color = Color.BLUE;//创建一个蓝色 是使用An ...
- 根据xml文件生成javaBean
原 根据xml文件生成javaBean 2017年08月15日 18:32:26 吃完喝完嚼益达 阅读数 1727 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出 ...
- eclips运行generatorConfig.xml文件生成代码
描述: 如何通过eclips工具来运行 generatorConfig.xml 文件来自动生成代码并获取数据(类似于mybaits逆向生成)? mybatis-generator:generate 2 ...
- WebAPI使用多个xml文件生成帮助文档
一.前言 上篇有提到在WebAPI项目内,通过在Nuget里安装(Microsoft.AspNet.WebApi.HelpPage)可以根据注释生成帮助文档,查看代码实现会发现是基于解析项目生成的xm ...
- WebAPI使用多个xml文件生成帮助文档(转)
http://www.cnblogs.com/idoudou/p/xmldocumentation-for-web-api-include-documentation-from-beyond-the- ...
- Android(java)学习笔记185:xml文件生成
1.xml文件: 用元素描述数据,跨平台. 2.利用传统的方式创建xml文件,下面是一个案例: 设计思路:建立一个学生管理系统,创建xml文件保存学生信息: (1)首先是布局文件activity_ma ...
- 【转】WebAPI使用多个xml文件生成帮助文档
来自:http://www.it165.net/pro/html/201505/42504.html 一.前言 上篇有提到在WebAPI项目内,通过在Nuget里安装(Microsoft.AspNet ...
随机推荐
- 奇怪吸引子---Coullet
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- [leetcode]Word Break @ Python
原题地址:https://oj.leetcode.com/problems/word-break/ 题意: Given a string s and a dictionary of words dic ...
- Focal Loss(RetinaNet) 与 OHEM
Focal Loss for Dense Object Detection-RetinaNet YOLO和SSD可以算one-stage算法里的佼佼者,加上R-CNN系列算法,这几种算法可以说是目标检 ...
- java正则校验,密码必须由字母和数字组成
一个匹配数字和字母密码的正则表达式 2011 年 12 月 14 日 | Filed under: 正则表达式 and tagged with: 密码 , 正则表达式 , 零宽断言 一个用户注册功能的 ...
- 【google面试题】求1到n的正数中1出现的次数的两种思路及其复杂度分析
问题描写叙述: 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.比如输入12,从1到12这些整数中包括1 的数字有1.10.11和12.1一共出现了5次. 这是一道广为流传的googl ...
- 转:从头开始编写基于隐含马尔可夫模型HMM的中文分词器
http://blog.csdn.net/guixunlong/article/details/8925990 从头开始编写基于隐含马尔可夫模型HMM的中文分词器之一 - 资源篇 首先感谢52nlp的 ...
- 红米1线刷救砖教程V5版(移动联通适用,线刷包永久有效)
红米1线刷救砖教程V5版(移动联通适用,线刷包永久有效) 原文来自:http://www.miui.com/thread-1890972-1-1.html?mobile=2 ,加了些自己的经验. (我 ...
- Docker登录失败
% docker login Username: xxxx Password: Email: xxxxxxx@yahoo.co.jp FATA[0033] Error response from ...
- php获取网址
#测试网址: http://localhost/blog/testurl.php?id=5 //获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br> ...
- C++结构变量数据对齐问题
为了避免混淆.做例如以下规定,下面代码若不加特殊说明都执行于32位平台,结构体的默认对齐值是8,各数据类型所占字节数分别为 char占一个字节 int占四个字节 double占八个字节. 两个样例 请 ...