/** @mainpage
TinyXML 是一个简单、小巧的 C++ XML 解析器,可以轻松集成到其他程序中。
简而言之,TinyXML 解析 XML 文档,并从中构建一个文档对象模型(DOM),该模型可以被读取、修改和保存。
XML 代表“可扩展标记语言”。它允许你创建自己的文档标记。HTML 在为浏览器标记文档方面做得非常好,而 XML 允许你定义任何类型的文档标记,例如描述一个用于日程管理应用程序的“待办事项”列表的文档。XML 是一种非常结构化且方便的格式。所有那些用于存储应用程序数据的随机文件格式都可以被 XML 取代。一个解析器适用于所有。
完整、正确且坦率地说难以阅读的规范的最佳位置是 http://www.w3.org/TR/2004/REC-xml-20040204/。一个(我真的很喜欢的)XML 入门教程可以在 http://skew.org/xml/tutorial 找到。
有多种方式可以访问和与 XML 数据交互。TinyXML 使用文档对象模型(DOM),这意味着 XML 数据被解析成可以浏览和操作的 C++ 对象,然后写入磁盘或其他输出流。你也可以从头开始用 C++ 对象构建一个 XML 文档,并将其写入磁盘或其他输出流。
TinyXML 设计为易于学习且上手快。它由两个头文件和四个 cpp 文件组成。只需将这些文件添加到你的项目中,就可以开始了。有一个示例文件 - xmltest.cpp - 可以帮助你入门。
TinyXML 在 ZLib 许可下发布,因此你可以在开源或商业代码中使用它。许可证的详细信息在每个源文件的顶部。
TinyXML 试图成为一个灵活的解析器,并产生真正正确且符合规范的 XML 输出。TinyXML 应该能在任何合理符合 C++ 标准的系统上编译。它不依赖异常或 RTTI。它可以在有或没有 STL 支持的情况下编译。TinyXML 完全支持 UTF-8 编码以及前 64k 个字符实体。
TinyXML 不会解析或使用 DTD(文档类型定义)或 XSL(可扩展样式表语言)。还有其他解析器(查看 www.sourceforge.org,搜索 XML)功能更全面。但它们也更大,在你的项目中设置需要更长时间,学习曲线更高,并且通常有更严格的许可。如果你在处理浏览器或有更完整的 XML 需求,TinyXML 不是适合你的解析器。
以下 DTD 语法目前在 TinyXML 中无法解析:
@verbatim ]> @endverbatim
因为 TinyXML 将此视为一个 !DOCTYPE 节点,其中非法嵌入了一个 !ELEMENT 节点。这个问题可能会在将来得到解决。
对于没有耐心的用户,这里有一个教程可以帮助你上手。这是一个很好的入门方式,但值得你花时间完整阅读这份(非常短的)手册。
TinyXML 是成熟、经过测试的代码。它非常稳定。如果你发现错误,请在 sourceforge 网站(www.sourceforge.net/projects/tinyxml)上提交错误报告。我们会尽快解决。
有一些改进的领域;如果你对参与 TinyXML 的工作感兴趣,请查看 sourceforge。
你可能觉得有用的 TinyXML 项目!(描述由项目提供。)
TinyXML 可以编译为使用或不使用 STL。使用 STL 时,TinyXML 使用 std::string 类,并完全支持 std::istream、std::ostream、operator<< 和 operator>>。许多 API 方法同时提供 'const char*' 和 'const std::string&' 形式。
当 STL 支持被编译排除时,完全不会包含任何 STL 文件。所有字符串类都由 TinyXML 自身实现。API 方法的所有输入都使用 'const char*' 形式。
使用编译时的 #define:
TIXML_USE_STL
来编译一个版本或另一个版本。这可以通过编译器传递,或者作为 "tinyxml.h" 的第一行设置。
注意:如果在 Linux 中编译测试代码,设置环境变量 TINYXML_USE_STL=YES/NO 将控制 STL 编译。在 Windows 项目文件中,提供了 STL 和非 STL 目标。在你的项目中,最简单的方法可能是在 tinyxml.h 的第一行添加 "#define TIXML_USE_STL"。
TinyXML 支持 UTF-8,允许操作任何语言的 XML 文件。TinyXML 也支持“传统模式”——在 UTF-8 支持之前使用的编码,可能最好描述为“扩展 ascii”。
通常,TinyXML 会尝试检测正确的编码并使用它。但是,通过在头文件中设置 TIXML_DEFAULT_ENCODING 的值,可以强制 TinyXML 始终使用一种编码。
TinyXML 将假定为传统模式,直到发生以下情况之一:
如果编码设置或检测不正确会发生什么?TinyXML 会尝试读取并传递看起来编码不正确的文本。你可能会得到一些奇怪的结果或乱码字符。你可能希望强制 TinyXML 使用正确的模式。
你可以通过使用 LoadFile( TIXML_ENCODING_LEGACY ) 或 LoadFile( filename, TIXML_ENCODING_LEGACY ) 强制 TinyXML 使用传统模式。你可以通过设置 TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY 来强制它始终使用传统模式。同样,你可以通过相同技术强制它使用 TIXML_ENCODING_UTF8。
对于使用英语 XML 的英语用户,UTF-8 与低 ASCII 相同。你不需要了解 UTF-8 或以任何方式修改代码。你可以将 UTF-8 视为 ASCII 的“超集”。
UTF-8 不是双字节格式——但它是 Unicode 的标准编码!TinyXML 目前不使用或直接支持 wchar、TCHAR 或 Microsoft 的 _UNICODE。经常看到术语“Unicode”不正确地指代 UTF-16,这是一种 Unicode 的宽字节编码。这是混淆的来源。
对于“高 ASCII”语言——几乎所有非英语语言——只要 XML 以 UTF-8 编码,TinyXML 可以同时处理所有语言。这可能有点棘手,较旧的操作系统和程序倾向于使用“默认”或“传统”代码页。许多应用程序(以及几乎所有现代应用程序)可以输出 UTF-8,但较旧或顽固(或干脆有缺陷的)应用程序仍然以默认代码页输出文本。
例如,日文系统传统上使用 SHIFT-JIS 编码。以 SHIFT-JIS 编码的文本无法被 TinyXML 读取。一个好的文本编辑器可以导入 SHIFT-JIS 然后保存为 UTF-8。
Skew.org 链接 在涵盖编码问题方面做得很好。
测试文件 "utf8test.xml" 是一个包含英语、西班牙语、俄语和简体中文的 XML。(希望它们被正确翻译)。文件 "utf8test.gif" 是 XML 文件的屏幕截图,在 IE 中渲染。注意,如果你的系统没有正确的字体(简体中文或俄语),即使你能正确解析它,你也看不到与 GIF 文件匹配的输出。还要注意,(至少在我的 Windows 机器上)控制台输出采用西方代码页,因此 Print() 或 printf() 无法正确显示该文件。这不是 TinyXML 的 bug——只是操作系统问题。TinyXML 没有丢失或销毁任何数据。控制台只是不渲染 UTF-8。
@verbatim & & < < > > " " ' ' @endverbatim
这些在读取 XML 文档时被识别,并转换为它们的 UTF-8 等价物。例如,文本的 XML 为:
@verbatim Far & Away @endverbatim
当从 TiXmlText 对象查询时,其 Value() 将为 "Far & Away",并在写回 XML 流/文件时以 & 符号表示。旧版本的 TinyXML“保留”字符实体,但新版本会将它们转换为字符。
此外,任何字符都可以通过其 Unicode 码点指定:语法 " " 或 " " 都表示不间断空格字符。
Print( FILE* )。输出到 C 标准流,包括所有 C 文件以及 stdout。
operator<<。输出到 C++ 流。
TiXmlPrinter。输出到 std::string 或内存缓冲区。
C 风格输出: - 基于 FILE* - Print() 和 SaveFile() 方法
生成格式化输出,带有大量空白,旨在尽可能易于人类阅读。速度非常快,并且容忍格式错误的 XML 文档。例如,包含 2 个根元素和 2 个声明的 XML 文档仍然可以打印。
C 风格输入: - 基于 FILE* - Parse() 和 LoadFile() 方法
快速、容错的读取。当你不使用 C++ 流时使用。
C++ 风格输出: - 基于 std::ostream - operator<<
生成紧凑输出,旨在用于网络传输而非可读性。取决于你系统对 ostream 类的实现,这些可能稍微慢一些。(也可能不慢。)不容忍格式错误的 XML:文档应包含正确的单个根元素。额外的根级别元素不会被流式输出。
C++ 风格输入: - 基于 std::istream - operator>>
从流中读取 XML,使其适用于网络传输。棘手之处在于知道 XML 文档何时完成,因为流中几乎肯定还有其他数据。TinyXML 将在读取根元素后假定 XML 数据完成。换句话说,构造不当且包含多个根元素的文档将无法正确读取。另请注意,由于 STL 的实现和 TinyXML 的局限性,operator>> 比 Parse 稍慢。
这是一个尚未令我满意的解决的问题。TinyXML 支持前两种方法。调用 TiXmlBase::SetCondenseWhiteSpace( bool ) 来设置所需行为。默认是压缩空白。
如果你更改默认设置,应在对解析 XML 数据做出任何调用之前调用 TiXmlBase::SetCondenseWhiteSpace( bool ),并且我不建议在设置后更改它。
在健壮地浏览 XML 文档时,检查方法调用的 null 返回非常重要。一个错误安全的实现可能会生成大量如下代码:
@verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // 终于能做一些有用的事情了。 @endverbatim
为了简化这种情况,引入了句柄。使用 TiXmlHandle 类,上述代码简化为:
@verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); if ( child2 ) { // 做一些有用的事情 @endverbatim
这要容易处理得多。有关更多信息,请参阅 TiXmlHandle。
TinyXML 可以跟踪文本文件中所有节点和属性的行和列源。TiXmlBase::Row() 和 TiXmlBase::Column() 方法返回节点在源文本中的位置。可以在 TiXmlDocument::SetTabSize() 中配置正确的制表符。
编译并运行 xmltest:
提供了 Linux Makefile 和 Windows Visual C++ .dsw 文件。只需编译并运行。它将文件 demotest.xml 写入你的磁盘并在屏幕上生成输出。它还通过打印使用不同技术发现的节点数量来测试遍历 DOM。
Linux makefile 非常通用,可以在许多系统上运行——目前已在 mingw 和 MacOSX 上进行测试。你不需要运行 'make depend'。依赖关系已硬编码。
PROFILE、DEBUG 和 TINYXML_USE_STL。详细信息(如果有)在 Makefile 中。
在 tinyxml 目录中,输入 "make clean" 然后 "make"。可执行文件 'xmltest' 将被创建。
将 tinyxml.cpp、tinyxml.h、tinyxmlerror.cpp、tinyxmlparser.cpp、tinystr.cpp 和 tinystr.h 添加到你的项目或 Makefile 中。就这样!它应该能在任何合理符合 C++ 标准的系统上编译。你不需要为 TinyXML 启用异常或 RTTI。
示例可能是最好的方式。以: @verbatim <?xml version="1.0" standalone=no> 去玩具店! 做账单 @endverbatim
这个待办事项列表不算什么,但足以说明问题。要读取这个文件(比如 "demo.xml"),你需要创建一个文档并解析它: @verbatim TiXmlDocument doc( "demo.xml" ); doc.LoadFile(); @endverbatim
然后就可以使用了。现在让我们看看一些行以及它们如何与 DOM 关联。
@verbatim
@endverbatim 第一行是一个声明,并转换为 TiXmlDeclaration 类。它将是文档节点的第一个子节点。 这是 TinyXML 解析的唯一指令/特殊标签。通常指令标签存储在 TiXmlUnknown 中,这样当保存回磁盘时命令不会丢失。 @verbatim @endverbatim 一条注释。将成为 TiXmlComment 对象。 @verbatim @endverbatim "ToDo" 标签定义了一个 TiXmlElement 对象。这个没有属性,但包含另外 2 个元素。 @verbatim @endverbatim 创建另一个 TiXmlElement,它是 "ToDo" 元素的子节点。该元素有 1 个属性,名称为 "priority",值为 "1"。 @verbatim 去 @endverbatim 一个 TiXmlText。这是一个叶节点,不能包含其他节点。它是 "Item" TiXmlElement 的子节点。 @verbatim @endverbatim 另一个 TiXmlElement,它是 "Item" 元素的子节点。 等等。 查看整个对象树,最终得到: @verbatim TiXmlDocument "demo.xml" TiXmlDeclaration "version='1.0'" "standalone=no" TiXmlComment " 我们的待办事项列表数据" TiXmlElement "ToDo" TiXmlElement "Item" 属性: priority = 1 TiXmlText "去" TiXmlElement "bold" TiXmlText "玩具店!" TiXmlElement "Item" 属性: priority=2 TiXmlText "做账单" @endverbatim