用C++解析XML一直用的tinyxml,轻便,简单。这里记录下一些自己的使用方法与心得。
对于用tinyxml解析xml,我一般只有三个步骤:
- 加载
- 获取节点
- 读取内容
1.加载
Tinyxml是由一堆类构成的,而加载用到的类是TiXmlDocument。要解析目标XML前都要将目标XML加载到TiXmlDocument对象中,之后的所有操作都将从TiXmlDocument对象出发,包括目标字符串和文件。
加载字符串用LoadFile(const char* buf);
加载文件用Parse(const char* filename);
具体的可去看函数声明
如下,是个有个简单的文档,存于名为class.xml的文档中
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <class> 3 <student ID="1" ID2="test"> 4 <Sex>男</Sex> 5 <Name>班长</Name> 6 </student> 7 <student ID="2">无</student> 8 </class>
我创建一个TiXmlDocument,此文介绍全为加载此文档前题下,当然如果是从网络或是别处传入的,只要直接传入内存地址指针就成了。
TiXmlDocument* doc = new TiXmlDocument(); doc->LoadFile("./class.xml");
当然,在使用前最重要的判断指针是否为NULL,之后讲的东西也一样,这是很重要的一点
if(doc == NULL){return;}
2.获取节点
当加载完成了,便开始解析了,而解析的过程,无非是从一个节点元素开始,往两个方面走,一个向子节点方向深入,一个往兄弟节点平移,而根据需求决定要不要取节点的值。一会详述。
首先我们解析下xml声明,而声明中有用的便是 编码方式。TiXmlDeclaration类表示声明,从doc中通过ToDeclaration()获得,而编码方式则是decl的Encoding(),返回的是const char*;
//获取文档的声明 TiXmlDeclaration* decl = doc->ToDeclaration(); if ( NULL != decl ) { std::string encoding = decl->Encoding(); //这里会返回“UTF-8" }
接下来,开始解析元素。一般XML都有一个根元素,根元素是所有元素的父元素。根元素可以由以下方法获得:
TiXmlElement* root = doc->RootElement();
这个方法可以获得根元素,此元素便是<class>了。
TiXmlElement类,表示元素类,是解析过程中的用的最多的一个类,可以表示所有<>内的元素,当然包括根元素。这里root是指向根元素,而如果你并不知道根元素的名称,可以能过root->Value()获得。而如果你知道这个XML文件的根节点名,笔者用XML一般做传输协议,基本都是知道整个XML的结构的,我推荐另一个方法获取根节点。
TiXmlElement* NodeRoot = doc->FirstChildElement("class");
上行代码表示获取doc的第一个class子节点,因为一开始我们就知道这个XML是以<class>为根节点,这样做不仅可以获取根节点,而且可以验证是不是以class为根节点的。
获取根节点成功后,接下来便是获取student节点了:
//不知道具体节点名 TiXmlElement* NodeStudent = NodeRoot->FirstChildElement();
std::cout << NodeStudent->Value << std::endl; //这里输出节点名,即student //知道节点名 TiXmlElement* NodeStudent = NodeRoot->FirstChildElement("student");
当前NodeStrudnt是指向<student ID="1" ID2="test">,而ID,ID2是元素student的属性,“1“,”test"是属性的值,下方的<sex><name>是子节点,也是元素。
想要获取ID=1可用以下代码
TiXmlAttribute* attr = NodeStudent->FirstAttribute(); if(NULL != attr) { std::cout << attr->Name() << endl; //这时输出ID std::cout << attr->Value() << endl; //这里输出1 } attr = attr->Next(); //这里指向第二个属性,attr->Next()操作时是不会自增长的,只是返回下一个属性,所以还要自己赋值 std::cout << attr->Value(); //这里当没有ID2属性时,会抛出异常
想要获得<Sex>只能通过父节点获得,而<Name>则可以同时通过兄弟节点获得
//先通过父节点获取 //不知道具体节点名,指向<Sex> TiXmlElement* NodeSex = NodeStudent->FirstChildElement(); //知道节点名,指向<class> TiXmlElement* NodeName = NodeStudent->FirstChildElement("Name"); //通过兄弟节点指向<class> TiXmlElement* NodeName = NodeSex->NextSiblingElement(); TiXmlElement* NodeName = NodeSex->NextSiblingElement("Name");
而如果想获得节点里的文本信息,可以通过以下方法获得,当然得是元素不为NULL的情况下
//1.可以通过GetText,缺点是当文本信息为空时,会抛了异常 std::cout << NodeSex->GetText() << endl; //输出“男” std::cout << NodeName->GetText() << endl; //输出“班长“ //2.可以过能GetChild判断是否有子文本,然后通过Value()获得 TiXmlNode* text = nodeSex->FirstChild(); if( NULL != text) std::cout << text.Value() <<endl; //输出”男“
如果有很多学生要遍历都可以
while(NULL != NodeStudent) { ...//相应的解析,取值 NodeStudent= NodeStudent->NextSiblingElement("stduent"); }
3.获取内容
第二部分好像已经讲过了,再总结下
获取元素名为 Value()
获取属性名 Name(),属性值Value()
获取文本信息:GetText(),这里要注意不能为空或者通过TiXmlNode的Value获取
以上,就是本人解析XML的常用方法,初稿,之后有时间再编辑修改, BY WenHY 无氏木
注意点:
1.XML是大小写区分的
2.一定要注意检察获取的东西是否为空
3.最后要释放doc