快速上手 TinyXML-2 不完全教程
TinyXML-2 不完全教程
XML 作为程序开发中非常常用的数据文档之一,各个语言或是开发环境都有对应的用于处理 XML 文件的库。在 C++ 语言中,TinyXML-2 就是这样的一个库。
TinyXML-2 是一个简单,小巧,高性能的 C++ 的 XML 解析器,它能够容易地集成到其他程序中。
与 TinyXML-2 有关的两个网页如下:
- GitHub 主页:https://github.com/leethomason/tinyxml2
- 在线帮助文档:http://leethomason.github.io/tinyxml2/
TinyXML-2 的接入
在 tinyxml2 中有两个主要文件:
- tinyxml2.cpp
- tinyxml2.h
通常来讲,你仅仅需要将上面的两个主要的文件放到你的工程中,就可以使用它了。在编译时只需要将这两个和其他的源文件一起编译即可。
另外,还有一个测试文件:
- xmltest.cpp
从这个文件里,我们可以看到关于 tinyxml2 的很多用法。不过仅仅是使用 tinyxml2 的话,可以暂时忽略这个文件。
使用 TinyXML-2 解析 XML 文件
通过 TinyXML-2 读取 XML 文件很简单,仅仅通过下面的两行代码,就能将一个 XML 文件解析到 XMLDocument 对象中:
XMLDocument doc;
doc.LoadFile( "dream.xml" );
在解析到 XMLDocument 对象中后,就可以通过这个对象来获取这个 XML 文件中的所有信息。这个对象跟其他的 C++ 对象一样,能够在栈上建立,也可以使用 new 或 delete 关键字在堆上创建或删除。
下面是一段读取和遍历 XML 文件的所有内容的代码,这也是这篇文章中最重要的部分了,如果看懂了的话,那么后面的内容就不用再看了:
这段代码也在这里 https://gist.github.com/Lee-swifter/traversingXMLUsingTinyXML,大家帮忙点个赞哈。。。
#include <iostream>
#include "tinyxml2.h"using namespace std;
using namespace tinyxml2;void traversingXML(XMLNode* node) {if(node == nullptr)return;if(node->ToDeclaration()) {auto declaration = dynamic_cast<XMLDeclaration*>(node);cout << "XML 声明,value=" << declaration->Value() << endl;}if(node->ToElement()) {auto element = dynamic_cast<XMLElement*>(node);cout << "XML 元素,name=" << element->Name() << ", value=" << element->Value() << endl;const XMLAttribute* attribute = element->FirstAttribute();while (attribute != nullptr) {cout << "\t属性 " << attribute->Name() << "=" << attribute->Value() << endl;attribute = attribute->Next();}}if(node->ToText()) {auto text = dynamic_cast<XMLText*>(node);cout << "XML 文本:" << text->Value() << endl;}if(node->ToComment()) {auto comment = dynamic_cast<XMLComment*>(node);cout << "XML 注释:" << comment->Value() << endl;}if(node->ToUnknown()) {auto unknown = dynamic_cast<XMLUnknown*>(node);cout << "XML 未知:" << unknown->Value() << endl;}if(node->ToDocument()) {auto document = dynamic_cast<XMLDocument*>(node);cout << "XML 文档:" << document->ErrorName() << endl;}if(node->NoChildren()) {return;}XMLNode* child = node->FirstChild();while(child != nullptr) {traversingXML(child);child = child->NextSibling();}
}int main(int argc, const char * argv[]) {XMLDocument xmlDocument;XMLError error = xmlDocument.LoadFile("test.xml");if(error != XML_SUCCESS) {std::cout << "读取 xml 失败:" << xmlDocument.ErrorStr() << endl;return EXIT_FAILURE;}traversingXML(&xmlDocument);return EXIT_SUCCESS;
}
但是在详细解析这段代码之前,我们需要了解 XMLDocument 的内存模型,才能进一步分析这段代码。
TinyXML-2 的内存模型
TinyXML-2 类型
上面这个图是 TinyXML-2 中用于表示 XML 内容的几个类的图。可见 TinyXML-2 将 XML 中的所有元素都归为 XMLNode。XMLNode 是一个抽象类,因此其继承出几种不同的类型以区分 XML 中的不同内容:
- XMLDocument 表示一个 XML 文档
- XMLElement 表示一个 XML 的元素
- XMLComment 表示一个 XML 中的注释
- XMLDeclaration 表示 XML 的声明,一般都是在 XML 最前面
- XMLText 表示一个 XML 中的文本信息
- XMLUnknow 未知的类型
这些类型光说一下可能不直观,所以,先放上一张示例图:
TinyXML-2 在内存中使用兄弟孩子表示法来表示生成 XML 的一个树,在 XMLNode 中最重要的两个方法就是:
- const XMLNode * FirstChild() const
- const XMLNode * NextSibling() const
TinyXML-2 中的兄弟孩子表示法
这两个方法是在兄弟孩子表示法中用于遍历的常用函数。对于兄弟孩子表示法不熟的人,看一下这张图:
在这里,我们可以只需要将图中的所有节点看成一个 XMLNode 对象就明白了。通过上面的两个方法就可以递归遍历一个 XML 中的所有节点。
对于一个 XMLNode,可以通过 Value()
方法获取其内容,而且可以通过对应的 ToXXX 方法,安全的转换为其子类型。
TinyXML-2 对 XML 的操作
结合上面所说的两点,一个遍历 XML 的代码就可以出来了:
void traversingXML(XMLNode* node) {//查看 node 节点printf(node->Value());if(node->NoChildren())return;XMLNode* child = node->FirstChild();while(child != nullptr) {traversingXML(child);child = child->NextSibling();}
}
如果需要更改 XML 的话,仅仅需要创建出 XMLNode 然后对其进行操作,并添加到其他的节点上。但是这里需要特别注意的一点是:任何 XMLDocument 的子节点,例如 XMLElement、XMLText 等,只能通过调用对应的方法来创建,即 XMLDocument::NewElement、XMLDocument::NewText 这种方法。尽管你可以拥有这些节点对象的指针,这些子节点仍然归属于其 XMLDocument 对象。当 XMLDocument 对象被删除时,它所包含的所有节点也会被删除。
对于一个 XML 来讲,最需要关注的就是这个 XML 对应的 XMLDocument 对象了。它可以用来创建子节点,并进行一些最主要的操作。对于节点的插入和删除,可以使用 XMLNode 的下面的一些方法:
- XMLNode * InsertFirstChild(XMLNode *addThis)
- XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
- XMLNode * InsertEndChild(XMLNode *addThis)
- void DeleteChild(XMLNode *node)
- void DeleteChildren()
例如:下面的代码将创建一个 XML 文件:
void createXML() {XMLDocument document;XMLDeclaration* declaration = document.NewDeclaration("xml version='1.0' encoding='utf-8' standalone='yes'");XMLComment* comment = document.NewComment("这是一个注释");XMLUnknown* unknow = document.NewUnknown("Unknow 类型");XMLElement* root = document.NewElement("svg");root->SetAttribute("height", "1080");root->SetAttribute("widht", "1920");root->SetAttribute("viewBox", "0 0 1920 1080");XMLElement* g = document.NewElement("g");XMLElement* path = document.NewElement("path");path->SetAttribute("stroke-width", "3.5");XMLText* text = document.NewText("text int path tag.");path->InsertEndChild(text);g->InsertEndChild(path);root->InsertEndChild(g);document.InsertEndChild(declaration);document.InsertEndChild(comment);document.InsertEndChild(unknow);document.InsertEndChild(root);document.SaveFile("test_save.xml");
}
其创建出来的 XML 文件如下:
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<!--这是一个注释-->
<!Unknow 类型>
<svg height="1080" widht="1920" viewBox="0 0 1920 1080"><g><path stroke-width="3.5">text int path tag.</path></g>
</svg>
使用 TinyXML-2 保存 XML 文件
想要将 XML 保存到文件中时,仅需要调用下面的方法:
XMLDocument doc;
...
doc.SaveFile( "foo.xml" );
几个需要注意的地方
这里是关于其主页上的几个特点的翻译,如果想快速上手 tinyxml2,并觉得自己不会踩坑,可以直接跳过。
文件编码
在解析 XML 时,TinyXML-2 仅使用 utf-8 编码,并假定所有的 XML 文件都是用 utf-8 进行编码的。
加载/保存的文件名将会不加修改地传递给底层操作系统。
空白字符
保留空白字符(默认)
Microsoft 关于空白字符的处理有一篇很牛逼的文章:http://msdn.microsoft.com/en-us/library/ms256097.aspx
在默认情况下,TinyXML-2 用一种合理的方式保留空白字符。按照 XML 规范的要求,所有newlines / carriage-returns / line-feeds 都被规范化为换行字符。
在文本中的空白字符将会保留。例如:
<element> Hello, World</element>
这个 XML 中,Hello
前面的空格和,
后面的两个空格将会被保留。在文本中的换行符也将会被保留,例如下面的 XML:
<element> Hello again,
World</element>
但是,在元素之间的空白字符不会被保留。因为跟踪和报告元素之间的空白内容是很尴尬的,而且通常也没有任何价值,于是乎,TinyXML-2 会将下面的两个 XNL 认作相同的内容:
<document>
<data>1</data>
<data>2</data>
<data>3</data>
</document><document><data>1</data><data>2</data><data>3</data></document>
删除空白字符
某些应用程序更希望将空白字符删掉,TinyXML-2 可以通过向 XMLDocument 的构造函数传入空白字符的参数来支持,默认情况下是保留空白字符。
当你使用 COLLAPSE_WHITESPACE
来删除空白字符时,TinyXML-2 将会
- 删除前导和末尾的空白字符
- 将换行符转换为一个空白字符
- 将连续的空白字符折叠成一个空白字符
但需要注意的是,使用COLLAPSE_WHITESPACE
会有性能影响,它本质上将倒是 XML 被解析两次。
错误报告
TinyXML-2 如果在解析 XML 时发生错误,那么它将会报告错误发生所在行的行号。此外,所有节点(元素、声明、文本、注释等)和属性在解析时都有一个行号记录。这样的话,应用程序就可以对解析的XML文档执行额外的验证。
特殊字符
TinyXML-2 能够识别一些定义好的特殊字符,即:
& &
< <
> >
" "
' '
在读取 XML 文档时,这些字符将会别识别为他们的 UTF-8 的值。例如,如果 XML
中一段文本是:
Far & Away
如果你调用从这个 XMLText 对象调用 Value() 获取其值时,将会得到 “Far & Away”。
快速上手 TinyXML-2 不完全教程相关推荐
- 阿里云商标注册快速上手笔记(新手图文教程)
阿里云商标注册图文教程快速上手笔记,本文以阿里云商标智能注册申请为例,商标智能注册申请需要用户手动填写商标类型.商标名称.商标图样.商标说明及商标分类表选择等操作,流程较为复杂,TM83商标网来详细说 ...
- cass读取dat文件_南方CASS教程+视频讲解+插件汇总,小白快速上手的测绘神器
南方CASS教程+视频讲解+插件汇总,小白快速上手的测绘神器 自CASS软件推出以来,市场占有率遥遥领先,已经成为业内应用最广.使用最方便快捷的软件品牌.也是用户量最大.升级最快.服务最好的主流成图和 ...
- thinkcmf5调用指定分类的二级_Tengine快速上手系列教程amp;视频:基于Python API的图片分类应用入门丨附彩蛋...
前言:近期,Tengine团队加班加点,好消息接踵而来,OpenCV 4.3.0发布,OPEN AI LAB AIoT智能开发平台Tengine与OpenCV合作共同加速边缘智能,Tengine再获业 ...
- xmind快速上手使用教程,提高工作效率
文章目录 1 xmind快捷键 1.1 文件 1.2 编辑 1.3 插入 1.4 查看 1.5 自定义快捷键 2 快速上手使用,创建一个好看的思维导图教程 3 使用xmind快速创建一个思维导图 1 ...
- TensorFlow 2.0 快速上手教程与手写数字识别例子讲解
文章目录 TensorFlow 基础 自动求导机制 参数优化 TensorFlow 模型建立.训练与评估 通用模型的类结构 多层感知机手写数字识别 Keras Pipeline * TensorFlo ...
- 申请 Let's Encrypt 数字证书,并安装cerbot快速上手教程~~
申请 Let's Encrypt 数字证书,并安装cerbot快速上手教程~~ Let's Encrypt SSL证书介绍 如今,越来越多的网站已经由HTTP迁移到HTTPS安全协议了.HTTPS不但 ...
- NexentaStor iSCSI/ NAS 存储服务器软件图解教程(3)——NMV快速上手指南Part2
NexentaStoriSCSI/NAS 存储服务器软件图解教程(3) Nexenta Management View (NMV)/*NexentaStor Web 管理界面*/快速上手指南Part ...
- 【Endnote】EndnoteX9快速上手教程
想得美,自己慢慢摸索才是硬道理,哪有什么快速上手教程,链接在下面 链接:https://pan.baidu.com/s/1Vtnaz90Iwp3I17M8ijxMWg 密码:ems7
- 快速上手Springboot项目(登录注册保姆级教程)
本文章对SpringBoot开发后端项目结构做了简单介绍,并示范了使用SpringBoot+MySQL实现登录的后端功能,与本博客的另一篇文章 Vue 实现登录注册功能(前后端分离完整案例) | Ma ...
- Debussy 快速上手教程
本文为转载,刚瞄了一眼,应该是在LINUX下的应用快速上手教程.Debussy是个很强大的看V代码及Debug V代码工具.你能方便地看到信号从哪里来到哪里去,比较强大.简单地用,用起来也比较简单.在 ...
最新文章
- ROS编程: 一些Tips
- 额外篇 | basemap(下)
- 开源一些Delphi系统:诗词成语字典
- SpringSecurity 认证通过后显示当前认证用户名
- mac pycharm安装设置_Mac系统Python、PyCharm安装及使用方法详解
- Python自学真的可以学好嘛?
- 前端js获取SpringMvc后台model中传值
- 如何加大jvm的内存和tomcat的内存
- Linux常见问题三则:Executable Path Is Not Absolute
- 日常笔记(持续更新)
- 高校科研项目管理系统
- 计算机论文题目_基于java的毕业设计题目_50例
- AD统一查看元器件得封装信息
- python画出分子化学空间分布(UMAP)
- 看了阿里找数据分析师的新规则,真让人头皮发麻!
- 余弦相似度-C#代码实现
- 和华明诚:提高店铺关注的操作方法
- NOI 2.6 动态规划 6045:开餐馆
- 从原子结构,半导体,PN结到MOS管和CMOS
- 20100919星期天最折磨人的一天。