博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TinyXML(C++ XML解析库)
阅读量:4167 次
发布时间:2019-05-26

本文共 5163 字,大约阅读时间需要 17 分钟。

写一个XML文件 TinyXML 是一个mini的C++ XML解析库,它是非验证的,它可以很容易的集成到其他的程序中.它解析一份XML doc,以此创建一个可以被读、写,保存的DOM.它主要的类层次架构,函数原形详细说明参看:

// 以下以简单的程序TinyXMLTest为例 TinyXML中最根本的就是Document,所以无论是需要写一个XML文件,还是要读,都必须从一个Document开始,就是(1)的动作,在此没有给构造函数一个参数是因为我们的目的是为了写出一个XML文件,文件的名字就是传给TiXmlDocument的参数。声明,文档,注释,文本,元素,不明类型都是TinyXmlNode的子类,都是一个Node,TinyXmlNode是一个很复杂的东西,它如上所示:

#include

#include "tinyxml.h"
using namespace std;
int main(int argc, char** argv)
{

// (1) create a XML document

TiXmlDocument *myDoc = new TiXmlDocument();
Document类型的节点建立好以后,就需要给该DOM树结构一个根,即下面的(2),(3),(5),由于TinyXml是非验证的,所以理论上他是可以有两个Document的,(在内部通过对类型的判断来避免这一情况的发生),由于根是一个元素,而元素本质上就是一个容器,他可以有子元素,文本等,由于属性可以有多个,所以在内部它有一个TinyXmlAttrbuiteSet的成员,用以储存之,而在TinyXmlAttrbuiteSet中所存的Attrbuites是通过带”哨兵”的链表来实现.在每次链接时,都是放置在最后一个位置

//(2) create the Root and connect it

TiXmlElement *RootElement = new TiXmlElement("人员组");
myDoc->LinkEndChild(RootElement);

//(3 )create a person and connect it

TiXmlElement *PersonElement = new TiXmlElement("人员");
RootElement ->LinkEndChild(PersonElement);
如(4)所示,如果一个元素有属性需要设置,通过调用SetAttribute()方法,可以实现目标,在设置时,会在Element的内部的链表上搜索,如果已经有相应的属性名,那么视之为改写,如果没有则添加.
//(4) set the attribute fo Person
PersonElement ->SetAttribute("ID", "1");

//(5) create Elementy name && age and connect them

TiXmlElement* NameElement = new TiXmlElement("姓名");
TiXmlElement* AgeElement = new TiXmlElement("年龄");
PersonElement ->LinkEndChild(NameElement);
PersonElement ->LinkEndChild(AgeElement);
如6所示,文本应该是XML中最好处理的tag类型了,它在DOM树结构中只能以“叶子”的形式存在.

//(6) set element Name && age and connect it

TiXmlText *NameContent = new TiXmlText("周星星");
TiXmlText *AgeContent = new TiXmlText("20");
NameElement ->LinkEndChild(NameContent);
AgeElement ->LinkEndChild(AgeContent);

最麻烦的应该就是(7)了,首先以”w”方式打开star.xml文件(如果不存在,则创建),在SaveFile的内部经过一些预处理后,就进入了一个从TinyXmlBase,继承而来的方法Print,在打印的过程中,按深度优先,前序方式进行。

(1) 打印出自己的名字和第一个’<’ eg:
(2) 判断是否有属性,有则依次打印,直到结束 eg:
(3) 根据是否有子元素确定是打印出”/>” 还是’>’
(4) 若有子元素,递归
(5) 打印完成,关闭文件
(6) SaveFile返回
// (7) save the file
myDoc ->SaveFile("star.xml");

读一个XML文件

前面简要的分析了一下,如何用TinyXML完成一个DOM树的输出,这儿将要给出一个如何读入XML文件,并提取其中数据的案例: 前一份文档写了,用TinyXML输出DOM,与读入XML文件为DOM的第一步骤就是实例化一个TinyXMLDocument的对象。

#include

#include"tinyxml.h"

using namespace std;

class TiXmlDocument;

int main(int argc, char** argv)

{

// (1)create a XML Doc object

TiXmlDocument* myDoc = new TiXmlDocument("sample.xml");

myDoc->LoadFile();

 

这看着最简单的LoadFile函数在进入内部的时候,那个繁杂,怎一个“难”字了得。在内部文件以”rb”的方式打开,以使对TinyXML 能对EOL归一化( reading in binary mode so that tinyxml can normalize the EOL) ,文件被成功打开后,将取得文件的大小,以下代码可以轻松完成:

fseek( file, 0, SEEK_END ); // LewGun
length = ftell( file );
fseek( file, 0, SEEK_SET );

在内部实例化一个std::string(针对使用STL而言,如果没有,则会使用TinyXmlString)。将文件中的所有数据读出,读到一个临时缓冲区buf中,然后 根据地XML的规范,在对XML文件进行解析前,需要让他们归一化,即:让“\r\n”,或者多个‘\r’字符转化为单个\n

if ( *p == 0xa )

{
// Newline character. No special rules for this. Append all the characters

// since the last string, and include the newline.

data.append( lastPos, (p-lastPos+1) ); // append, include the newline

++p; // move past the newline
lastPos = p; // and point to the new buffer (may be 0)
assert( p <= (buf+length) );
}

将这append到刚才的那个string中。归一化完成,然后就调用Parse函数进行解析,在解析的过程中由刚才的串string将这c_str()后,逐个字符的的处理,在处理的过程中,由于在生成XML文档,为了结构良好,会有相当多的空格,要将之去掉,根据提取的字符,来针对不同的类型比如表示是一个声明,其将会是一个注释,实例化不同的类,在实例化的过程中仍然是以当前的节点即myDoc为根,来生成DOM树,当对string比对完成,相应的DOM树也生成完成.

 

// (2)获取到对应元素上的文本值和属性值

取得根元素.的并输出的操作

TiXmlElement* rootElement = myDoc->RootElement();

cout <<>Value() <<>

这与前面的LinkEndChild在理论上是一个相对应的操作

TiXmlElement* FirstPerson = rootElement->FirstChildElement();

// get the first persons's node Name && Age and attribute ID

TiXmlElement *NameElement = FirstPerson->FirstChildElement();

TiXmlElement *AgeElement = NameElement->NextSiblingElement();

此句代码需要主意的是,由于元素的内部的attributeSet是通过双向链表来放置属性的,且它有一个哨兵节点,该节点一直被放置在最后,而FirstAttribute()会在内部调用

First(){ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }

Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }

TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();

在此AgeElement/NameElement的子女就是Text类型的对象,对之取值就是前文的”周星星”/20

cout << NameElement->Value() << endl;

cout << AgeElement ->Value() << endl;

cout << IDAttribute->Value() << endl;

}

 

下面再贴个示例

/*功能2:按某个字段从xml档中获取到对应的值*/	TiXmlElement* pElement1 = rootElement->FirstChildElement();	bool bFind = false;	if(pElement1)	{		while(!bFind)		{			TiXmlElement* pElement2 = pElement1->FirstChildElement("field");			if(!pElement2)			{				pElement1 = pElement1->FirstChildElement();				if(!pElement1)				{					break;				}				continue;			}			for(;pElement2;)			{				//获得指定元素上的属性值				TiXmlAttribute* pAttribute = pElement2->FirstAttribute();				std::string strAttrName = pAttribute->Name();				std::string strTarget = "name";				while(pAttribute)				{					strAttrName = pAttribute->Name();					if(!strAttrName.compare(strTarget))					{						strTarget = "epcid";						std::string strTargetValue = pAttribute->Value();						if(!strTargetValue.compare(strTarget))						{							cout << strTargetValue << "--------" << endl;							bFind = true;							break;						}					}					pAttribute = pAttribute->Next();				}				if(bFind)				{					break;				}				pElement2 = pElement2->NextSiblingElement();			}		}	}

 

转载地址:http://ogoxi.baihongyu.com/

你可能感兴趣的文章
数组中累加和为定值K的最长子数组长度
查看>>
idea添加gradle模块报错The project is already registered
查看>>
在C++中如何实现模板函数的外部调用
查看>>
HTML5学习之——HTML 5 拖放
查看>>
HTML5学习之——HTML 5 Canvas vs. SVG
查看>>
HTML5学习之——HTML 5 应用程序缓存
查看>>
HTML5学习之——HTML 5 Web Workers
查看>>
HTML5学习之——HTML 5 Canvas
查看>>
HTML5学习之——HTML5 内联 SVG
查看>>
HTML5学习之——HTML 5 服务器发送事件
查看>>
SVG学习之——HTML 页面中的 SVG
查看>>
SVG 形状学习之——SVG圆形
查看>>
SVG 滤镜学习之——SVG 滤镜
查看>>
mysql中用命令行复制表结构的方法
查看>>
hbase shell出现ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException
查看>>
让代码变得更优雅-Lombok
查看>>
解决Rhythmbox乱码
查看>>
豆瓣爱问共享资料插件发布啦
查看>>
Ubuntu10.10 CAJView安装 读取nh\kdh\caj文件 成功
查看>>
kermit的安装和配置
查看>>