简介:
这个号称是最快的DOM模型XML分析器,在使用它之前我都是用TinyXML的,因为它小巧和容易上手,但真正在项目中使用时才发现如果分析一个比较大的XML时TinyXML还是表现一般,所以我们决定使用RapidXML作为替换。当然是为了获取更好的性能,经过我们的初步试验后发现确实比TinyXML好,但看到网上关于rapidxml的资料零散,而且也缺乏一份较为权威的说明文档,找来找去还是得看官方的英文手册。所以我又下单了,翻译官方提供的手册,希望给各位朋友提供一些绵薄之力。

1. RapidXml 是什么?
RapidXML是一个试图创建最快的XML DOM分析器,当然同时也保留它的可用性、移植性和适当的W3C兼容性。它是一个用C++编写的即用分析器,在相同的数据上它的分析速度接近于strlen()函数。
整个分析器就包含在单独的一个头文件中,所以不需要任何的构建和链接。当你使用的时候只需将 rapidxml.hpp 文件复制到一个合适的地方(例如你的工程目录下),然后在任何需要它的地方包含一下即可。或许你也会用到 rapidxml_print.hpp 头文件里的打印函数。

1.1 Dependencies And Compatibility(依赖和兼容)
RadpidXML除了使用到标准C++库(<cassert>, <cstdlib>, <new> 和 <exception>, 除非异常被关闭了)的很小一个子集外没有关联其它东西了。它能被任何标准编译器所编译,并已在Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, 和 Comeau 4.3.3. 中测试通过。也就是说在这些编译器上没出现任何的警告信息,即使在最高警告级别上。
1.2 Character Types And Encodings(字符类型和编码)
RadpidXML并不知道字符集的类型(译注:因为它是基于模板,可以自定义字符类型),所以在窄字符和宽字符下都能工作。当前版本并不完全支持UTF-16和UTF-32,所以使用宽字符稍微有点不适合。不管怎样,如果数据的字节顺序与当前系统匹配,它能成功分析包含UTF-16或UTF-32 的wchar_t 字符串。UTF-8是完全支持的,包括所有的数值字符引用,这些字符会被扩展到适当的UTF-8字节顺序(除非你打开parse_no_utf8 flag 标记)。
要注意RapidXml不会对 name() 和 value() 函数返回的字符串进行解码,因为函数会根据源代码文件本身的编码模式来编码(译注:也就是说如果你的源代码文件编码格式为ANSI,则name()函数返回的字符串编码也是ANSI,如果源代码文件的编码格式为UTF-8,字符串编码也是UTF-8)。Rapidxml能解释和扩展下列的字符应用:' & " < > &#...;其它字符引用不会被展开。

1.3 Error Handling (错误处理)
默认情况下,RapidXml使用C++异常来报告错误,如果你不喜欢这个行为,可以使用RAPIDXML_NO_EXCEPTIONS定义来制止异常代码,请参考 parse_error 类和 parse_error_handler() (http://rapidxml.sourceforge.net/manual.html#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1) 函数。
1.4 Memory Allocation(内存分配)
RadpidXml使用一个特别的内存池对象来分配所有的节点和属性,因为直接使用 new 操作符来分配太慢了,池中的内存分配可用 memory_pool::set_allocator() (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1memory__pool_c0a55a6ef0837dca67572e357100d78a_1c0a55a6ef0837dca67572e357100d78a) 函数来自定义,详细信息请看 memory_pool (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1memory__pool) 类。
1.5 W3C Compliance(W3C兼容)
RapidXml并不是一个与W3C完全一致的分析器,主要原因是忽略了 DOCTYPE 声明。还有一些其它原因,如兼容性不是很好,但是,它能成功分析和生成与W3C文件组(有关XML处理器的规格设计超过1000个文件)定义的完整XML树。即使在不良的情况下它也能对空白符进行正常化处理和对一部分字符集实体进行替换。
1.6 API Design(API设计)
为了尽可能的减少代码量,RadpidXML API已经很简约了,并且为了能在它嵌入的环境中更容易使用,一些附加的功能被分割在不同的头文件中:rapidxml_utils.hpp 和rapidxml_print.hpp (http://rapidxml.sourceforge.net/manual.html#rapidxml__print_8hpp)。这两个头文件并不是必须的,并且当前也没有相关文档(但是代码中有注释)。
1.7 Reliability(可靠性)
RadpidXML很健壮,因为它通过了一大堆的单元测试。已经特别小心地确保分析器的稳定性,不管你扔什么文本给它。其中的一项单元测试用了随机产生100,000个XML文档错误,RapidXml也能创建它(还未更正)。当这些错误被引入后RapidXml还是能通过这项测试,并且不会被破坏和进入死循环。
其它的单元测试也和RapidXMl进行肉搏,稳定的XML分析器,和其它为了符合一大推文档和功能的测试。
另外RapidXml进行了1000多个W3C兼容性文件测试,并且都能取得正确的结果。其它的测试包括对API函数的测试,并且测试各种各样的分析模式。

1.8 Acknowledgements(致谢)
I would like to thank Arseny Kapoulkine for his work on pugixml (http://code.google.com/p/pugixml), which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml (http://www.codeproject.com/soap/pugxml.asp), from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

2. Two Minute Tutorial(两分钟教程)
2.1 Parsing(分析)
下面的代码示范了RapidXml分析一个以0结尾的字符串text:
using namespace rapidxml;
xml_document<> doc; // 字符类型默认为char
doc.parse<0>(text); // 0表示默认分析标记
doc对象现在是一个DOM树,代表已分析的XML。因为所有的RadpidXml接口都包含在命名空间 rapidxml中,用户要么加入此命令空间,要么使用完整的命名(译注:即要使用doc必须使用 rapidxml::xml_docment<> doc),类xml_document代表一个DOM层次的根节点。除了是公共的继承点,它还是一个xml_node 和memory_pool。xml_document::parse()函数的模板参数是用来指定分析标记的,它可以用来对分析器进行微调。但要注意,标记必须是一个编译器的常数。
2.2 Accessing The DOM Tree(访问DOM树)
要访问DOM树,使用xml_node和xml_attribute类中的方法即可:
cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
xml_node<> *node = doc.first_node("foobar");
cout << "Node foobar has value " << node->value() << "\n";
for (xml_attribute<> *attr = node->first_attribute();
attr; attr = attr->next_attribute())
{
cout << "Node foobar has attribute " << attr->name() << " ";
cout << "with value " << attr->value() << "\n";
}
2.3 Modifying The DOM Tree(修改DOM树)
分析器生成的DOM树完全可以修改。可以增加和删除节点和属性,还有他们的内容。下面的例子创建了一个HTML文档,并有个单独的链接到google.com网站:
xml_document<> doc;
xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
doc.append_node(node);
xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
node->append_attribute(attr);

其中一个特点是节点和属性都不拥有它们的名称和值。这是因为通常它们都只保存指向源文本的指针。所以,当关联一个新的名称或值给节点时,要特别小心字符串的生命周期。最简单的方法是通过xml_document内存池来分配字符串。在上面的例子中其实是不需要的,因为我们只关联了字符常量。但是下面的例子就使用memory_pool::allocate_string() (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859)函数来分配节点名称(拥有与文档一样的生命周期),并将它关联到一个新的节点:
xml_document<> doc;
char *node_name = doc.allocate_string(name); // 分配字符串并将名称复制进去
xml_node<> *node = doc.allocate_node(node_element, node_name); // 为 node_name设置节点名称
查看 参考 小节可看到这个接口的描述。
2.4 Printing XML(打印XML)
你可以将xml_document和xml_node对象输出为一个XML字符串。使用print()函数或操作符 operator<<,在 rapidxml_print.hpp (http://rapidxml.sourceforge.net/manual.html#rapidxml__print_8hpp) 头文件中可找到这些定义。
using namespace rapidxml;
xml_document<> doc; // 字符类型默认为 char
// ... 一些填充文档的代码
// 使用标准字符流operator <<
std::cout << doc;

// 用print函数来输出流,指定了打印参数
print(std::cout, doc, 0); // 0 表示默认

// 通过输出迭代器来打印字符串
std::string s;
print(std::back_inserter(s), doc, 0);

// 通过输出迭代器来输出到内存缓存里
char buffer[4096]; // 你必须保证缓存足够大!
char *end = print(buffer, doc, 0); // end包含了指向最后一个字符的指针
*end = 0; // 在XML后面添加字符终止符
3. Differences From Regular XML Parsers(与常规XML分析器的不同之处)
RapidXml是一个原位分析器,能提供非常快的分析速度。原位的意思是分析器并不做字符串的拷贝,而是在DOM层次中放置指向源文本的指针。
3.1 Lifetime Of Source Text(源文本的生命周期)
原位分析需要源文本的生命周期与XML文档对象一样长。如果源文本销毁了,DOM树里的节点名称和值也会跟着销毁,而且,空白符处理,字符集转换,和0结尾的字符串都需要在分析期间被修改(但不是破坏性的)。这就使得Rapidxml进行下一步分析时字符串不再有效了。
但是在大多数情况下,这些都不是严重的问题。
3.2 Ownership Of Strings(字符串的所有权)
Rapidxml生成的节点和属性都不拥有它们自己的名称和值字符串。它们只是保留了指向名称和值的指针。也就是说,当你用xml_base::name(const Ch *) (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1xml__base_e099c291e104a0d277307fe71f5e0f9e_1e099c291e104a0d277307fe71f5e0f9e) 或 xml_base::value(const Ch *) (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1xml__base_18c7469acdca771de9b4f3054053029c_118c7469acdca771de9b4f3054053029c) 函数时必须非常小心的设置这些值。要小心保证传递进来的字符串拥有与节点和属性一样长的生命周期。也可以简单地通过使用文档的内存池来分配这些字符串。使用memory_pool::allocate_string() (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859)函数可达到此目的。
3.3 Destructive Vs Non-Destructive Mode(破坏模式和非破坏模式) 
默认情况下,当分析器进行分析处理时会修改源文本。这时因为需要做字符集的转换、空白符常规化、字符串0终止。
可能在某些情况下这个行为不好,例如源文本在一个只读的内存中,或者是从文件中直接映射过来的。通过使用适当的分析标记(parse_non_destructive),源文本修改模式可以被关闭。但是,因为Rapidxml做了原位分析,该标记明显有下列的副作用:
· 不作空白符的正常化处理
· 不作实体引用转换
· 名称和值都是非0终止的,你必须使用xml_base::name_size() (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c) 和 xml_base::value_size() (http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db)函数来告诉他们结束。

RAPIDXML 中文手册,根据官方文档完整翻译!相关推荐

  1. 【DPDK工程师手册】 —— 官方文档,最新视频,开源项目,论文,大厂内部ppt,知名工程师一览表

    ✨✨✨[DPDK工程师手册] -- 官方文档,最新视频,开源项目,论文,大厂内部ppt,知名工程师一览表 -- 数据平面开发套件

  2. CUDA10.0官方文档的翻译与学习之编程接口

    目录 背景 用nvcc编译 编译工作流 二进制适配性 ptx适配性 应用适配性 C/C++适配性 64位适配性 cuda c运行时 初始化 设备内存 共享内存 页锁主机内存 可移植内存 写合并内存 映 ...

  3. python pymssql - pymssql模块官方文档的翻译

    译者注:译者博客(http://blog.csdn.net/lin_strong),转载请保留这条.此为pymssql模块version2.1.4官方文档的翻译,仅供学习交流使用,请勿用于商业用途. ...

  4. python的pymssql模块的报错_python pymssql - pymssql模块官方文档的翻译

    译者注:译者博客(http://blog.csdn.net/lin_strong),转载请保留这条.此为pymssql模块version2.1.4官方文档的翻译,仅供学习交流使用,请勿用于商业用途. ...

  5. Pytorch官方文档英语翻译

    深度学习Pytorch-Pytorch官方文档英语翻译 1. a-e 1.1 span 跨度 1.2 blended 混合的 1.3 criterion 标准 1.4 deprecated 弃用的 1 ...

  6. 【百度AI_文字识别】示例身份证图片识别(代码官方文档完整,只需获得修改参数、下载类)

    文章目录 提取身份证信息 第一步:登录 第二步:获取资源 第三步:获取access_token参数(AuthService.java) 第四步:请求代码Idcard.java 第五步:修改Idcard ...

  7. AsyncDisplayKit官方文档个人翻译

    迁移老文章到掘金 文档比较老了,不适用最新的2.0 AsyncDisplayKit 官方文档 最近在拆解学习AsyncDisplayKit这个很知名的轮子,发现这个轮子内容还是非常庞大的,想要分解学习 ...

  8. iOS 9官方文档(翻译)

    iOS9已经发布一段时间了,我也在最近升级了Xcdoe 7.0正式版,升级后才发现又有了很多奇妙的变化,于是查看官方文档的一些解释,顺便做了一些翻译,和大家分享一下(转载请注明出处). iPad多任务 ...

  9. 参加Apache Pulsar官方文档的翻译工作

    从9月开始接触Pulsar,我进行了简单的了解后,便开始进行系统的学习.目前市面上没有任何中文的资料,当然学习新的知识,这也不算个问题.我从官方文档一点点读起,在读的过程中为了方便以后反复学习和对照, ...

  10. Hyperledger-indy 官方文档人工翻译

    博客内容为Hyperledger-indy官方部署文档的中文翻译,翻译内容系原创,转载注明来源 [说明] (1)[撰写目的] Hyperledger-indy的中文资料较少,希望能为初次接触Hyper ...

最新文章

  1. Python 类—类属性(私有属性、公有属性、实例属性、局部变量)类方法(实例方法、静态方法)
  2. 从头理解self-attention机制
  3. linux系统命令学习系列-文件和目录管理
  4. php 爬虫去重,浅谈动态爬虫与去重(续)
  5. 图解Java 开发教程
  6. shell中的PS命令的含义
  7. spring @Value注解#和$区别
  8. [重要!] SAP Spartacus加载网络请求的entity状态切换,统一在loader.reducer.ts里完成
  9. Echart 5.0+版本报错Error in data(): “TypeError: Cannot read properties of undefined (reading ‘graphic‘)“
  10. postgreSQL源码分析——索引的建立与使用——GIN索引(1)
  11. 苹果下微信浏览器返回上一页不刷新问题解决方案
  12. nacos启动报错 db.num is null【已解决】
  13. android自定义图标下载,Android使用IconFont矢量图标库
  14. 基于51单片机的烟雾温度火灾报警器 LCD1602显示proteus仿真
  15. ​特拉华大学彭曦教授招收2021 Fall全奖博士生
  16. java多态的三种表现形式
  17. 区别:αβ^T、βα^T、αα^T、(Aα)(Aα)^T、β^Tα、α^Tβ、α^Tα、(Aα)^T(Aα)
  18. hdu1877 又一版 A+B (栈)
  19. docker 搭建在线vscode编辑器
  20. Windows畸形文件夹

热门文章

  1. OKHttp原理讲解之基本概念
  2. 局域网计算机共享加密码,局域网文件共享设置密码的方法
  3. SCM供应链管理系统解决方案:实现供应可视化、管理信息化,成本可控化
  4. 企业要实现用计算机完成存货管理,关于当前企业存货管理存在的问题及其完善措施...
  5. Windows 中使用苹果 macOS 动态桌面壁纸
  6. osgearth加载mapbox在线高程数据
  7. 如何把HTML背景图片变透明,photoshop怎样把图片背景变透明
  8. 大数据时代下的人工智能医疗
  9. c语言字符串不能是数字,C语言判断字符串是否为数字
  10. 注册公司选小规模还是一般人?四种判别方式讲得明明白白