RAPIDXML手册
版本 1.13
版权所有 (C) 2006, 2009 Marcin Kalicinski
有关许可证信息,请参阅随附的文件许可证 .txt。
目录
1. 什么是 RapidXml?
1.1 依赖性和兼容性
1.2 字符类型和编码
1.3 错误处理
1.4 内存分配
1.5 W3C 合规性
1.6 API 设计
1.7 可靠性
1.8 致谢
2.两分钟教程
2.1 解析
2.2 访问 DOM 树 2.3 修改 DOM 树
2.4 打印 XML
3.与常规 XML 解析器
的区别 3.1 源文本
的生存期 3.2 字符串
的所有权 3.3 破坏性与非破坏性模式
4.性能
4.1 与其他解析器
的比较 5.参考
1. 什么是 RapidXml?
RapidXml 试图创建最快的 XML DOM 解析器,同时保留可用性、可移植性和合理的 W3C 兼容性。它是一个用 C++ 编写的原位解析器,解析速度接近在相同数据上执行的 strlen()
函数。
整个解析器包含在单个头文件中,因此不需要构建或链接。要使用它,您只需要将 rapidxml.hpp
文件复制到一个方便的地方(例如您的项目目录),并将其包含在需要的地方。您可能还希望使用标头 rapidxml_print.hpp
中包含的打印功能。
1.1 依赖关系和兼容性
RapidXml 除了标准C++库(<cassert
>、<cstdlib
>、<new
> 和 <exception>
,除非禁用异常)之外,没有其他依赖项。它应该在任何合理兼容的编译器上编译,并在 Visual C++ 2003、Visual C++ 2005、Visual C++ 2008、gcc 3、gcc 4 和 Comeau 4.3.3 上进行了测试。请注意,即使启用了最高警告级别,也不会在这些编译器上生成警告。
1.2 字符类型和编码
RapidXml 与字符类型无关,可以处理窄字符和宽字符。当前版本不完全支持 UTF-16 或 UTF-32,因此使用宽字符在某种程度上是无能为力的。但是,如果数据的字节序与计算机的字节序匹配,则它应该成功解析包含 UTF-16 或 UTF-32 wchar_t
字符串。完全支持 UTF-8,包括所有数字字符引用,这些引用被扩展为适当的 UTF-8 字节序列(除非启用parse_no_utf8标志)。
请注意,RapidXml 不执行解码 - name() 和 value() 函数返回的字符串将包含使用与源文件相同的编码编码的文本。Rapidxml理解并扩展了以下字符引用: ' & “ < > &#...;
其他字符引用不会展开。
1.3 错误处理
默认情况下,RapidXml 使用 C++ 异常来报告错误。如果不希望出现此行为,则可以定义RAPIDXML_NO_EXCEPTIONS来抑制异常代码。有关更多信息,请参见 parse_error 类和 parse_error_handler() 函数。
1.4 内存分配
RapidXml 使用一个特殊的内存池对象来分配节点和属性,因为使用 new
运算符直接分配太慢了。可以使用 memory_pool::set_allocator() 函数自定义池执行的基础内存分配。有关详细信息,请参阅第 memory_pool 类。
1.5 W3C 合规性
RapidXml 不是符合 W3C 的解析器,主要是因为它忽略了 DOCTYPE 声明。还有许多其他轻微的不兼容问题。尽管如此,它仍然可以成功地解析和生成 W3C 一致性套件中所有有效 XML 文件的完整树(超过 1000 个专门设计用于查找 XML 处理器缺陷的文件)。在破坏性模式下,它对一小组内置实体执行空格规范化和字符实体替换。
1.6 API设计
RapidXml API 是简约的,以尽可能减小代码大小,并便于在嵌入式环境中使用。其他便利功能在单独的标头中提供:rapidxml_utils.hpp
和 rapidxml_print.hpp
。这些标头的内容不是库的重要组成部分,并且当前未记录(代码中的注释除外)。
1.7 可靠性
RapidXml 非常健壮,并附带了大量的单元测试。我们特别注意确保解析器的稳定性,无论向它抛出什么源文本。其中一个单元测试生成 100,000 个随机损坏的 XML 文档变体,这些变体(未损坏时)包含 RapidXml 识别的所有构造。当 RapidXml 正确识别出已引入错误,并且不会崩溃或无限循环时,它就通过了此测试。
另一个单元测试将 RapidXml 与另一个结构良好的 XML 解析器进行正面交锋,并验证它们的输出是否在各种小型和大型文档中匹配。
另一个测试向 RapidXml 提供来自 W1000C 合规性套件的 3 多个测试文件,并验证是否获得了正确的结果。还有一些其他测试可以单独验证每个 API 函数,并测试各种解析模式是否按预期工作。
1.8 致谢
我要感谢 Arseny Kapoulkine 在 pugixml 上所做的工作,这是这个项目的灵感来源。还要感谢 Kristen Wegner 创建了 pugxml,pugixml 就是从中衍生出来的。Janusz Wohlfeil 友好地在我无权访问的硬件上运行了 RapidXml 速度测试,使我能够扩展性能比较表。
2. 两分钟教程
2.1 解析
以下代码使 RapidXml 解析名为 : object 的以零结尾的字符串现在是包含已解析 XML 表示形式的 DOM 树的根。由于所有 RapidXml 接口都包含在 namespace 中,因此用户必须将此命名空间的内容带入范围,或者完全限定所有名称。类 xml_document 表示 DOM 层次结构的根。通过公有继承,也是xml_node和memory_pool。xml_document::p arse() 函数的模板参数用于指定解析标志,您可以使用这些标志微调解析器的行为。请注意,标志必须是编译时常量。text
using namespace rapidxml;
xml_document<> doc; // character type defaults to char
doc.parse<0>(text); // 0 means default parse flags
doc
rapidxml
2.2 访问 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 修改 DOM 树
解析器生成的 DOM 树是完全可修改的。可以添加/删除节点和属性,并更改其内容。下面的示例创建一个 HTML 文档,其唯一内容是指向 google.com 网站的链接: 一个怪癖是节点和属性不拥有其名称和值的文本。这是因为通常它们只存储指向源文本的指针。因此,在为节点分配新名称或值时,必须注意确保字符串的正确生存期。实现此目的的最简单方法是从 xml_document 内存池中分配字符串。在上面的示例中,这不是必需的,因为我们只分配字符常量。但是下面的代码使用 memory_pool::allocate_string() 函数来分配节点名称(该名称将与文档具有相同的生存期),并将其分配给一个新节点: 查看参考部分,了解整个接口的描述。
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<> doc;
char *node_name = doc.allocate_string(name); // Allocate string and copy name into it
xml_node<> *node = doc.allocate_node(node_element, node_name); // Set node name to node_name
2.4 打印XML
您可以将 AND 对象打印成 XML 字符串。使用 header() 中定义的 print() 函数或运算符<<。xml_document
xml_node
rapidxml_print.hpp
using namespace rapidxml;
xml_document<> doc; // character type defaults to char
// ... some code to fill the document
// Print to stream using operator <<
std::cout << doc;
// Print to stream using print function, specifying printing flags
print(std::cout, doc, 0); // 0 means default printing flags
// Print to string using output iterator
std::string s;
print(std::back_inserter(s), doc, 0);
// Print to memory buffer using output iterator
char buffer[4096]; // You are responsible for making the buffer large enough!
char *end = print(buffer, doc, 0); // end contains pointer to character after last printed character
*end = 0; // Add string terminator after XML
3. 与常规 XML 解析器的区别
RapidXml 是一个原位解析器,这使得它能够实现非常高的解析速度。In-situ 意味着解析器不会复制字符串。相反,它会在 DOM 层次结构中放置指向源文本的指针。
3.1 源文本的生存期
原位分析要求源文本的生存时间至少与文档对象一样长。如果源文本被销毁,DOM 树中节点的名称和值也会被销毁。此外,空格处理、字符实体转换和字符串的零终止要求在解析期间修改源文本(但请参阅非破坏性模式)。这使得文本在被 RapidXml 解析后就无法进行进一步处理。
然而,在许多情况下,这些都不是严重的问题。
3.2 字符串的所有权
RapidXml 生成的节点和属性不拥有其名称和值字符串。他们只是拿着指向他们的指针。这意味着在使用 xml_base::name(const Ch *) 或 xml_base::value(const Ch *) 函数手动设置这些值时必须小心。必须注意确保传递的字符串的生存期至少与节点/属性的生存期一样长。实现它的最简单方法是从文档拥有的memory_pool中分配字符串。为此,请使用 memory_pool::allocate_string() 函数。
3.3 破坏性与非破坏性模式
默认情况下,解析器在解析过程中修改源文本。这是实现字符串的字符实体转换、空格规范化和零终止所必需的。
在某些情况下,这种行为可能是不可取的,例如,如果源文本驻留在只读内存中,或者直接从文件映射到内存。通过使用适当的分析器标志 (parse_non_destructive),可以禁用源文本修改。但是,由于 RapidXml 是原位解析的,因此它显然具有以下副作用:
- 未进行空格规范化
- 未进行实体引用转换
- 名称和值不是以零结尾的,您必须使用 xml_base::name_size() 和 xml_base::value_size() 函数来判断它们的结束位置
4. 性能
RapidXml 通过使用以下几种技术来实现其速度:
- 原位解析。在构建 DOM 树时,RapidXml 不会复制字符串数据,例如节点名称和值。相反,它存储指向源文本内部的指针。
- 使用模板元编程技术。这允许它将大部分工作转移到编译时间。通过模板的魔力,C++ 编译器为您使用的解析器标志的任意组合生成单独的解析代码副本。在每个副本中,所有可能的决策都是在编译时做出的,所有未使用的代码都被省略了。
- 广泛使用查找表进行解析。
- 手动调整的 C++,在几个最流行的 CPU 上完成分析。
这导致了一个非常小而快速的代码:一个解析器,它是根据每次调用的确切需求定制的。
4.1 与其他解析器的比较
下表将 RapidXml 的速度与其他一些解析器以及对相同数据执行的 strlen()
函数进行了比较。在现代 CPU(截至 2007 年)上,您可以预期解析吞吐量接近 1 GB/s。根据经验,解析速度比 Xerces DOM 快 50-100 倍,比 TinyXML 快 30-60 倍,比 pugxml 快 3-12 倍,比 pugixml 快 5% - 30%,pugixml 是我所知道的最快的 XML 解析器。
- 测试文件是一个真实世界的 50kB 大小、中等密度的 XML 文件。
- 所有计时都是通过使用奔腾兼容 CPU 中的 RDTSC 指令完成的。
- 不使用按配置文件优化。
- 所有解析器都以最快的模式运行。
- 结果以每个字符的 CPU 周期数给出,因此 CPU 的频率无关紧要。
- 结果是大量运行的最小值,以最大程度地减少操作系统活动、任务切换、中断处理等的影响。
- 测试文件的单次解析大约需要 1/10 毫秒,因此在大量运行时,很有可能达到至少一次无中断连续状态,并获得不受干扰的结果。
平台 | 编译器 | strlen() | RapidXml的 | 普吉XML 0.3 | pugxml的 | TinyXml的 |
---|---|---|---|---|---|---|
奔腾 4 | MSVC 8.0 | 2.5 | 5.4 | 7.0 | 61.7 | 298.8 |
奔腾 4 | GCC 4.1.1 | 0.8 | 6.1 | 9.5 | 67.0 | 413.2 |
核心 2 | MSVC 8.0 | 1.0 | 4.5 | 5.0 | 24.6 | 154.8 |
核心 2 | GCC 4.1.1 | 0.6 | 4.6 | 5.4 | 28.3 | 229.3 |
Athlon XP系列 | MSVC 8.0 | 3.1 | 7.7 | 8.0 | 25.5 | 182.6 |
Athlon XP系列 | GCC 4.1.1 | 0.9 | 8.2 | 9.2 | 33.7 | 265.2 |
奔腾 3 | MSVC 8.0 | 2.0 | 6.3 | 7.0 | 30.9 | 211.9 |
奔腾 3 | GCC 4.1.1 | 1.0 | 6.7 | 8.9 | 35.3 | 316.0 |
(*)所有结果均以源文本每个字符的 CPU 周期为单位
类 模板 RapidXML::memory_pool
在 rapidxml.hpp
中定义 xml_document 的基类
描述
解析器使用此类来创建新的节点和属性,而不会产生动态内存分配的开销。在大多数情况下,您不需要直接使用此类。但是,如果您需要手动创建节点或修改节点的名称/值,建议您使用相关xml_document memory_pool来分配内存。这不仅比使用新
运算符分配它们更快,而且它们的生存期将与文档的生存期相关联,这可能只是内存管理。
调用 allocate_node() 或 allocate_attribute() 函数以从池中获取新节点或属性。您还可以调用 allocate_string() 函数来分配字符串。然后,可以将此类字符串用作节点的名称或值,而无需担心其生存期。请注意,没有 free(
) 函数 -- 当调用 clear() 函数或销毁池时,所有分配都会立即释放。
也可以创建一个独立的memory_pool,并使用它来分配节点,其生存期不会与任何文档绑定。
池维护 RAPIDXML_STATIC_POOL_SIZE
字节的静态分配内存。在静态内存耗尽之前,不会进行动态内存分配。当静态内存耗尽时,pool 会使用全局 new[] 和 delete[]
运算符分配大小为 RAPIDXML_DYNAMIC_POOL_SIZE
的其他内存块。可以通过设置自定义分配例程来更改此行为。使用 set_allocator() 函数来设置它们。
节点、属性和字符串的分配以 RAPIDXML_ALIGNMENT
字节对齐。此值默认为目标体系结构上指针的大小。
为了从解析器获得绝对最佳性能,重要的是从单个连续的内存块分配所有节点。否则,在两个(或多个)不相交的内存块之间跳转时,缓存未命中会大大减慢解析速度。如果需要,您可以调整RAPIDXML_STATIC_POOL_SIZE
、RAPIDXML_DYNAMIC_POOL_SIZE
和RAPIDXML_ALIGNMENT
,以获得最佳的内存浪费,从而降低性能。为此,请在包含 rapidxml.hpp 文件之前定义它们的值。
参数
中文
已创建节点的字符类型。
构造 函数 memory_pool::memory_pool
概要
memory_pool();
描述
使用默认分配器函数构造空池。
破坏者 memory_pool::~memory_pool
概要
~memory_pool();
描述
销毁池并释放所有内存。这会导致释放池分配的节点占用的内存。从池中分配的节点不再有效。
函数 memory_pool::allocate_node
概要
xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);
描述
从池中分配一个新节点,并选择性地为其分配名称和值。如果无法容纳分配请求,此函数将抛出 std::bad_alloc
。如果通过定义 RAPIDXML_NO_EXCEPTIONS 禁用异常,此函数将调用 rapidxml::p arse_error_handler() 函数。
参数
类型
要创建的节点的类型。
名字
要分配给节点的名称,或 0 表示不指定任何名称。
价值
要分配给节点的值,或 0 表示不分配任何值。
name_size
要分配的名称的大小,或 0 根据名称字符串自动计算大小。
value_size
要分配的值的大小,或 0 根据值字符串自动计算大小。
返回
指向已分配节点的指针。此指针永远不会为 NULL。
函数 memory_pool::allocate_attribute
概要
xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);
描述
从池中分配一个新属性,并选择性地为其分配名称和值。如果无法容纳分配请求,此函数将抛出 std::bad_alloc
。如果通过定义 RAPIDXML_NO_EXCEPTIONS 禁用异常,此函数将调用 rapidxml::p arse_error_handler() 函数。
参数
名字
要分配给属性的名称,或 0 表示不指定名称。
价值
要分配给属性的值,或 0 表示不指定任何值。
name_size
要分配的名称的大小,或 0 根据名称字符串自动计算大小。
value_size
要分配的值的大小,或 0 根据值字符串自动计算大小。
返回
指向已分配属性的指针。此指针永远不会为 NULL。
函数 memory_pool::allocate_string
概要
Ch* allocate_string(const Ch *source=0, std::size_t size=0);
描述
从池中分配给定大小的 char 数组,并选择性地将给定的字符串复制到该数组中。如果无法容纳分配请求,此函数将抛出 std::bad_alloc
。如果通过定义 RAPIDXML_NO_EXCEPTIONS 禁用异常,此函数将调用 rapidxml::p arse_error_handler() 函数。
参数
源
String 用于初始化分配的内存,或 0 表示不初始化它。
大小
要分配的字符数,或从源字符串长度自动计算的字符数为零;如果 size 为 0,则必须指定源字符串并以 null 结尾。
返回
指向已分配的 char 数组的指针。此指针永远不会为 NULL。
函数 memory_pool::clone_node
概要
xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0);
描述
克隆xml_node及其子节点和属性的层次结构。节点和属性是从此内存池中分配的。名称和值不会被克隆,而是在克隆和源之间共享。可以选择将结果节点指定为第二个参数,在这种情况下,其内容将替换为克隆的源节点。当您想要克隆整个文档时,这很有用。
参数
源
要克隆的节点。
结果
用于放置结果的节点,或 0 用于自动分配结果的节点
返回
指向克隆节点的指针。此指针永远不会为 NULL。
函数 memory_pool::clear
概要
void clear();
描述
清除池。这会导致释放池分配的节点占用的内存。从池中分配的任何节点或字符串将不再有效。
函数 memory_pool::set_allocator
概要
void set_allocator(alloc_func *af, free_func *ff);
描述
设置或重置池的用户定义的内存分配函数。仅当尚未从池中分配内存时,才能调用此函数,否则结果未定义。分配函数不得在失败时返回无效指针。它应该抛出、停止程序或使用 longjmp()
函数将控制权传递给程序的其他位置。如果它返回无效指针,则结果未定义。
用户定义的分配函数必须具有以下形式: void *allocate(std::size_t size);
void free(void *指针);
参数
自动对焦
分配函数,或 0 恢复默认函数
ff
自由功能,或 0 恢复默认功能
RapidXml::p arse_error 类
在 rapidxml.hpp 中定义
描述
分析错误异常。发生错误时,分析器会引发此异常。使用 what() 函数获取人类可读的错误消息。使用 where() 函数获取指向源文本中检测到错误的位置的指针。
如果不需要解析器引发异常,则可以通过在包含 rapidxml.hpp 之前定义RAPIDXML_NO_EXCEPTIONS宏来禁用它。这将导致解析器调用 rapidxml::p arse_error_handler() 函数,而不是抛出异常。此函数必须由用户定义。
此类派生自 std::exception
类。
构造 函数 parse_error::p arse_error
概要
parse_error(const char *what, void *where);
描述
构造分析错误。
function parse_error::what
Synopsis
virtual const char* what() const;
Description
Gets human readable description of error.
Returns
Pointer to null terminated description of the error.
function parse_error::where
Synopsis
Ch* where() const;
Description
Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.
Returns
Pointer to location within the parsed string where error occured.
class template rapidxml::xml_attribute
Defined in rapidxml.hpp
Inherits from xml_base
Description
Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.
Parameters
中文
要使用的字符类型。
构造 函数 xml_attribute::xml_attribute
概要
xml_attribute();
描述
构造具有指定类型的空属性。如果手动分配属性,请考虑使用适当xml_document memory_pool。
功能xml_attribute::d ocument
概要
xml_document<Ch>* document() const;
描述
获取哪个属性是子属性的文档。
返回
指向包含此属性的文档的指针,如果没有父文档,则为 0。
函数 xml_attribute::p revious_attribute
概要
xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取上一个属性,可以选择匹配属性名称。
参数
名字
要查找的属性的名称,或 0 返回上一个属性,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向 found 属性的指针,如果未找到,则为 0。
函数 xml_attribute::next_attribute
概要
xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取下一个属性,可以选择匹配属性名称。
参数
名字
要查找的属性的名称,或 0 返回下一个属性,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向 found 属性的指针,如果未找到,则为 0。
类 模板 RapidXML::xml_base
在 rapidxml.hpp
中定义 xml_attribute xml_node 的基类
描述
用于实现常用函数的 xml_node 和 xml_attribute基类:name()、name_size()、value()、value_size() 和 parent()。
参数
中文
要使用的字符类型
构造 函数 xml_base::xml_base
概要
xml_base();
函数 xml_base::name
概要
Ch* name() const;
描述
获取节点的名称。名称的解释取决于节点的类型。请注意,如果在解析过程中选择了 rapidxml::p arse_no_string_terminators 选项,则 name 不会以零结尾。
使用 name_size() 函数确定名称的长度。
返回
节点的名称,如果节点没有名称,则为空字符串。
函数 xml_base::name_size
概要
std::size_t name_size() const;
描述
获取节点名称的大小,不包括终止符。无论名称是否为零终止,此函数都能正常工作。
返回
节点名称的大小(以字符为单位)。
函数 xml_base::value
概要
Ch* value() const;
描述
获取节点的值。值的解释取决于节点的类型。请注意,如果在解析过程中选择了 rapidxml::p arse_no_string_terminators 选项,则 value 不会以零结尾。
使用 value_size() 函数确定值的长度。
返回
节点的值,如果节点没有值,则为空字符串。
函数 xml_base::value_size
概要
std::size_t value_size() const;
描述
获取节点值的大小,不包括终止符字符。无论 value 是否为零终止,此函数都能正常工作。
返回
节点值的大小(以字符为单位)。
函数 xml_base::name
概要
void name(const Ch *name, std::size_t size);
描述
将节点名称设置为非以零结尾的字符串。请参 阅字符串的所有权 。
请注意,节点不拥有其名称或值,它只存储指向它的指针。它不会在销毁时删除或以其他方式释放指针。用户有责任正确管理字符串的生存期。实现它的最简单方法是使用文档的memory_pool来分配字符串 - 在文档销毁时,字符串将自动释放。
必须单独指定 name 的大小,因为 name 不必以零结尾。使用 name(const Ch *) 函数自动计算长度(字符串必须以零结尾)。
参数
名字
要设置的节点的名称。不必为零终止。
大小
名称的大小,以字符为单位。如果存在零终止符,则不包括零终止符。
函数 xml_base::name
概要
void name(const Ch *name);
描述
将节点名称设置为以零结尾的字符串。另请参阅 Ownership Of Strings 和 xml_node::name(const Ch *, std::size_t)。
参数
名字
要设置的节点的名称。必须以零终止。
函数 xml_base::value
概要
void value(const Ch *value, std::size_t size);
描述
将 node 的值设置为非以零结尾的字符串。请参 阅字符串的所有权 。
请注意,节点不拥有其名称或值,它只存储指向它的指针。它不会在销毁时删除或以其他方式释放指针。用户有责任正确管理字符串的生存期。实现它的最简单方法是使用文档的memory_pool来分配字符串 - 在文档销毁时,字符串将自动释放。
值的大小必须单独指定,因为它不必以零结尾。使用 value(const Ch *) 函数自动计算长度(字符串必须以零结尾)。
如果元素具有 node_data 类型的子节点,则在打印时它将优先于元素值。如果要使用值操作元素的数据,请使用解析器标志 rapidxml::p arse_no_data_nodes 来防止解析器创建数据节点。
参数
价值
要设置的节点的值。不必为零终止。
大小
值的大小(以字符为单位)。如果存在零终止符,则不包括零终止符。
函数 xml_base::value
概要
void value(const Ch *value);
描述
将 node 的值设置为以零结尾的字符串。另请参阅 Ownership Of Strings 和 xml_node::value(const Ch *, std::size_t)。
参数
价值
要设置的节点的 Vame。必须以零终止。
函数 xml_base::p arent
概要
xml_node<Ch>* parent() const;
描述
获取节点父级。
返回
指向父节点的指针,如果没有父节点,则为 0。
类 模板 RapidXML::xml_document
在 rapidxml.hpp
中定义 继承自 xml_node memory_pool
描述
此类表示 DOM 层次结构的根。它也是通过公共继承xml_node和memory_pool。使用 parse() 函数从以零结尾的 XML 文本字符串构建 DOM 树。parse() 函数使用 xml_document 函数为节点和属性分配内存,这些函数继承自 memory_pool。若要访问文档的根节点,请使用文档本身,就像它是xml_node一样。
参数
中文
要使用的字符类型。
构造 函数 xml_document::xml_document
概要
xml_document();
描述
构造空的 XML 文档。
函数xml_document::p arse
概要
void parse(Ch *text);
描述
根据给定的标志分析以零结尾的 XML 字符串。传递的字符串将被解析器修改,除非使用 rapidxml::p arse_non_destructive 标志。该字符串必须在文档的生存期内保留。如果出现错误,将抛出 rapidxml::p arse_error 异常。
如果要分析文件的内容,必须首先将文件加载到内存中,然后传递指向其开头的指针。确保数据以零终止。
文档可以解析为多次。每次对 parse 的新调用都会删除以前的节点和属性(如果有),但不会清除内存池。
参数
发短信
要解析的 XML 数据;指针是非常量,表示此数据可能被解析器修改的事实。
函数 xml_document::clear
概要
void clear();
描述
通过删除所有节点并清除内存池来清除文档。文档池拥有的所有节点都将被销毁。
类 模板 RapidXML::xml_node
在 rapidxml.hpp
中定义 继承自 xml_document xml_base
基类
描述
表示 XML 文档节点的类。每个节点可能具有关联的名称和值字符串,这些字符串可通过 name() 和 value() 函数获得。名称和值的解释取决于节点的类型。可以使用 type() 函数确定节点类型。
请注意,解析后,节点的名称和值(如果有)都将指向用于解析的源文本的内部。因此,此文本必须在节点的生存期内保留在内存中。
参数
中文
要使用的字符类型。
构造 函数 xml_node::xml_node
概要
xml_node(node_type type);
描述
构造具有指定类型的空节点。请考虑使用memory_pool适当的文档来手动分配节点。
参数
类型
要构造的节点的类型。
函数 xml_node::type
概要
node_type type() const;
描述
获取节点的类型。
返回
节点类型。
功能xml_node::d ocument
概要
xml_document<Ch>* document() const;
描述
获取哪个节点是子节点的文档。
返回
指向包含此节点的文档的指针,如果没有父文档,则为 0。
函数 xml_node::first_node
概要
xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取第一个子节点,可以选择匹配节点名称。
参数
名字
要查找的子项的名称,或返回第一个子项的 0,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向已找到子项的指针,如果未找到,则为 0。
函数 xml_node::last_node
概要
xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取最后一个子节点,可以选择匹配节点名称。如果节点没有子节点,则行为未定义。使用 first_node() 测试节点是否有子节点。
参数
名字
要查找的子项的名称,或 0 返回最后一个子项,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向已找到子项的指针,如果未找到,则为 0。
函数 xml_node::p revious_sibling
概要
xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取上一个同级节点,可以选择匹配节点名称。如果节点没有父节点,则行为未定义。使用 parent() 测试节点是否有父节点。
参数
名字
要查找的兄弟姐妹的名称,或 0 返回上一个兄弟姐妹,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向已找到同级的指针,如果未找到,则为 0。
函数 xml_node::next_sibling
概要
xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取下一个同级节点,可以选择匹配节点名称。如果节点没有父节点,则行为未定义。使用 parent() 测试节点是否有父节点。
参数
名字
要查找的兄弟姐妹的名称,或 0 返回下一个兄弟姐妹,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向已找到同级的指针,如果未找到,则为 0。
函数 xml_node::first_attribute
概要
xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取节点的第一个属性,可以选择匹配属性名称。
参数
名字
要查找的属性的名称,或 0 返回第一个属性,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向 found 属性的指针,如果未找到,则为 0。
函数 xml_node::last_attribute
概要
xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
描述
获取节点的最后一个属性,可以选择匹配属性名称。
参数
名字
要查找的属性的名称,或 0 返回最后一个属性,无论其名称如何;如果此字符串为非零,则此字符串不必以零结尾name_size
name_size
名称大小(以字符为单位)或 0 以根据字符串自动计算大小
case_sensitive
名称比较是否应区分大小写;不区分大小写的比较仅适用于 ASCII 字符
返回
指向 found 属性的指针,如果未找到,则为 0。
函数 xml_node::type
概要
void type(node_type type);
描述
设置节点的类型。
参数
类型
要设置的节点类型。
函数 xml_node::p repend_node
概要
void prepend_node(xml_node< Ch > *child);
描述
预置新的子节点。前面的子项成为第一个子项,所有现有子项都向后移动一个位置。
参数
孩子
要预置的节点。
函数 xml_node::append_node
概要
void append_node(xml_node< Ch > *child);
描述
追加新的子节点。附加的子项成为最后一个子项。
参数
孩子
要追加的节点。
函数 xml_node::insert_node
概要
void insert_node(xml_node< Ch > *where, xml_node< Ch > *child);
描述
在节点内的指定位置插入新的子节点。指定节点之后(包括指定节点)的所有子节点都将向后移动一个位置。
参数
哪里
放置插入孩子的位置,或 0 插入到后面。
孩子
要插入的节点。
函数 xml_node::remove_first_node
概要
void remove_first_node();
描述
删除第一个子节点。如果节点没有子节点,则行为未定义。使用 first_node() 测试节点是否有子节点。
函数 xml_node::remove_last_node
概要
void remove_last_node();
描述
删除节点的最后一个子节点。如果节点没有子节点,则行为未定义。使用 first_node() 测试节点是否有子节点。
函数 xml_node::remove_node
概要
void remove_node(xml_node< Ch > *where);
描述
从节点中删除指定的子节点。
函数 xml_node::remove_all_nodes
概要
void remove_all_nodes();
描述
删除所有子节点(但不包括属性)。
函数 xml_node::p repend_attribute
概要
void prepend_attribute(xml_attribute< Ch > *attribute);
描述
将新属性追加到节点。
参数
属性
要预置的属性。
函数 xml_node::append_attribute
概要
void append_attribute(xml_attribute< Ch > *attribute);
Description
Appends a new attribute to the node.
Parameters
attribute
Attribute to append.
function xml_node::insert_attribute
Synopsis
void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute);
Description
Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.
Parameters
where
Place where to insert the attribute, or 0 to insert at the back.
attribute
Attribute to insert.
function xml_node::remove_first_attribute
概要
void remove_first_attribute();
描述
删除节点的第一个属性。如果节点没有属性,则行为未定义。使用 first_attribute() 测试节点是否具有属性。
函数 xml_node::remove_last_attribute
概要
void remove_last_attribute();
描述
删除节点的最后一个属性。如果节点没有属性,则行为未定义。使用 first_attribute() 测试节点是否具有属性。
函数 xml_node::remove_attribute
概要
void remove_attribute(xml_attribute< Ch > *where);
描述
从节点中删除指定的属性。
参数
哪里
指向要删除的属性的指针。
函数 xml_node::remove_all_attributes
概要
void remove_all_attributes();
描述
删除节点的所有属性。
枚举node_type
描述
枚举列出分析器生成的所有节点类型。使用 xml_node::type() 函数查询节点类型。
值
node_document
文档节点。名称和值为空。
node_element
元素节点。Name 包含元素名称。值包含第一个数据节点的文本。
node_data
数据节点。名称为空。值包含数据文本。
node_cdata
CDATA 节点。名称为空。值包含数据文本。
node_comment
注释节点。名称为空。值包含注释文本。
node_declaration
声明节点。名称和值为空。声明参数(version、encoding 和 standalone)位于节点属性中。
node_doctype
一个 DOCTYPE 节点。名称为空。值包含 DOCTYPE 文本。
node_pi
PI 节点。名称包含目标。值包含指令。
功能parse_error_handler
概要
void rapidxml::parse_error_handler(const char *what, void *where);
描述
当通过定义RAPIDXML_NO_EXCEPTIONS禁用异常时,将调用此函数以通知用户有关错误的信息。它必须由用户定义。
此函数无法返回。如果是这样,则结果是不确定的。
一个非常简单的定义可能看起来像这样: void rapidxml::p arse_error_handler(const char *what, void *where) { std::cout << “解析错误:” << what << “\n”; std::abort(); }
参数
什么
人类可读的错误描述。
哪里
指向检测到错误的字符数据的指针。
功能打印
概要
OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0);
描述
将 XML 打印到给定的输出迭代器。
参数
外
要打印到的输出迭代器。
节点
要打印的节点。传递xml_document以打印整个文档。
标志
控制 XML 打印方式的标志。
返回
输出迭代器,指向紧跟在打印文本最后一个字符之后的位置。
功能打印
概要
std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0);
描述
将 XML 打印到给定的输出流。
参数
外
要打印到的输出流。
节点
要打印的节点。传递xml_document以打印整个文档。
标志
控制 XML 打印方式的标志。
返回
输出流。
函数运算符<<
概要
std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node);
描述
将格式化的 XML 打印到给定的输出流。使用默认打印标志。使用 print() 函数自定义打印过程。
参数
外
要打印到的输出流。
节点
要打印的节点。
返回
输出流。
parse_no_data_nodes
概要
const int parse_no_data_nodes = 0x1;
描述
Parse 标志指示解析器不创建数据节点。第一个数据节点的文本仍将放置在父元素的值中,除非还指定了 rapidxml::p arse_no_element_values 标志。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_no_element_values
概要
const int parse_no_element_values = 0x2;
描述
Parse 标志指示解析器不要使用第一个数据节点的文本作为父元素的值。可以使用 |算子。请注意,打印时元素节点的子数据节点优先于其值。也就是说,如果元素具有一个或多个子数据节点和一个值,则该值将被忽略。如果要使用元素值操作数据,请使用 rapidxml::p arse_no_data_nodes 标志来阻止创建数据节点。
参见 xml_document::p arse() 函数。
parse_no_string_terminators
概要
const int parse_no_string_terminators = 0x4;
描述
parse 标志指示分析器不要在源文本中的字符串后放置零终止符。默认情况下,将放置零个终止符,以修改源文本。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_no_entity_translation
概要
const int parse_no_entity_translation = 0x8;
描述
Parse 标志指示分析器不翻译源文本中的实体。默认情况下,将翻译实体,修改源文本。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_no_utf8
概要
const int parse_no_utf8 = 0x10;
描述
Parse 标志指示解析器禁用 UTF-8 处理并假定纯 8 位字符。默认情况下,UTF-8 处理处于启用状态。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_declaration_node
概要
const int parse_declaration_node = 0x20;
描述
指示解析器创建 XML 声明节点的 parse 标志。缺省情况下,不创建声明节点。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_comment_nodes
概要
const int parse_comment_nodes = 0x40;
描述
Parse 标志指示解析器创建注释节点。缺省情况下,不创建注释节点。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_doctype_node
概要
const int parse_doctype_node = 0x80;
描述
解析标志指示解析器创建 DOCTYPE 节点。缺省情况下,不会创建 doctype 节点。尽管 W3C 规范最多允许一个 DOCTYPE 节点,但 RapidXml 将静默地接受具有多个节点的文档。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_pi_nodes
概要
const int parse_pi_nodes = 0x100;
描述
指示解析器创建 PI 节点的解析标志。默认情况下,不会创建 PI 节点。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_validate_closing_tags
概要
const int parse_validate_closing_tags = 0x200;
描述
Parse 标志指示分析器验证结束标记名称。如果未设置,则结束标记内的名称与解析器无关。默认情况下,不会验证结束标记。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_trim_whitespace
概要
const int parse_trim_whitespace = 0x400;
描述
Parse 标志指示解析器修剪数据节点的所有前导和尾随空格。默认情况下,不会修剪空格。此标志不会导致分析器修改源文本。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_normalize_whitespace
概要
const int parse_normalize_whitespace = 0x800;
描述
Parse 标志指示解析器将数据节点的所有空格运行压缩为单个空格字符。数据的前导和尾随空格的修剪由 rapidxml::p arse_trim_whitespace 标志控制。默认情况下,空格不会规范化。如果指定了此标志,则将修改源文本。可以使用 |算子。
参见 xml_document::p arse() 函数。
parse_default
概要
const int parse_default = 0;
描述
解析标志,表示解析器的默认行为。这始终等于 0,因此所有其他标志可以简单地组合在一起。通常,没有必要通过使用其否定 (~) 值来禁用标志,从而不方便地禁用标志。这也意味着每个标志的含义都是对默认设置的否定。例如,如果标志名称为 rapidxml::p arse_no_utf8,则表示默认启用 utf-8,使用该标志将禁用它。
参见 xml_document::p arse() 函数。
parse_non_destructive
概要
const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
描述
禁止对源文本进行任何修改的分析标志的组合。这也导致更快的解析。但是,请注意,将发生以下情况:
- 节点的名称和值不会以零结尾,您必须使用 xml_base::name_size() 和 xml_base::value_size() 函数来确定名称和值的结束位置
- 实体不会被翻译
- 空格不会被规范化
参见 xml_document::p arse() 函数。
parse_fastest
概要
const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
描述
解析标志的组合可在不牺牲重要数据的情况下实现尽可能快的解析。
参见 xml_document::p arse() 函数。
parse_full
概要
const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
描述
分析标志的组合,导致提取的数据量最大。这通常会导致解析速度最慢。
参见 xml_document::p arse() 函数。
print_no_indenting
概要
const int print_no_indenting = 0x1;
描述
指示打印机禁止缩进 XML 的打印机标志。请参阅 print() 函数。