MiniXML中文文档
- 格式:doc
- 大小:222.50 KB
- 文档页数:55
TinyXml使用指南(1) 作者:tamsyn 来源: 时间:2006-8-16 【字体:大中小】〖双击滚屏〗在这里我们并不是要讲解如何使用XML,或在网页中使用它。
而是要在C/C++中使用它。
详细一点就是在C/C++嵌套使用XML文件。
要在C/C++中使用XML文件,你就必须需要一个能分析XML文件的函数库。
在这方面有很多,比如libxml2,tinxml,expat等等很多。
而我使用的是tinyxml,为什么要使用它呢?因为它很小巧,只有两个头文件和四个CPP文件。
正如作者在tinyxml官方文件中所说的,如果你不是想在浏览器中使用XML,那么tinyxml非常适合你。
我们下面来看一下tinyxml是如何在C/C++中建立XML文件的。
char floader[200],buffer[200];TiXmlDocument* m_xmlDoc = new TiXmlDocument();TiXmlElement xElement("player");sprintf(buffer,"%d", 1);xElement.SetAttribute("admin", buffer);TiXmlElement xPos("pos");sprintf(buffer,"%d",2);xPos.SetAttribute("x", buffer);sprintf(buffer,"%d",3);xPos.SetAttribute("y", buffer);sprintf(buffer,"%d",4);xPos.SetAttribute("zone", buffer);xElement.InsertEndChild(xPos);m_xmlDoc->InsertEndChild(xElement);sprintf(floader,"%s.xml", "antking");m_xmlDoc->SaveFile(floader);delete m_xmlDoc;这段简单的代码的作用就是将用户数据保存在XML文件中。
TinyXML中文文档六月08TinyXML中文文档TinyXML No Comments »完整显示 1 2 3 4 5 6 7  译注:本文是TinyXML 2.5.2版本Document的中文文档,经原作者Lee Thomason同意由hansen翻译,如有误译或者错漏,欢迎指正。
版权:版权归原作者所有,翻译文档版权归本人hansen所有,转载请注明出处。
原文:/tinyxmldocs/index.html 0;TinyXml 文档2.5.2TinyXMLTinyXML是一个简单小巧,可以很容易集成到其它程序中的C++ XML解析器。
它能做些什么简单地说,TinyXML解析一个XML文档并由此生成一个可读可修改可保存的文档对象模型(DOM)。
XML的意思是“可扩展标记语言“(eXtensible Markup Language)。
它允许你创建你自己的文档标记。
在为浏览器标记文档方面HTML做得很好,然而XML允许你定义任何文档标记,比如可以为一个组织者应用程序定义一个描述“to do”列表的文档。
XML拥有一个结构化并且方便的格式,所有为存储应用程序数据而创建的随机文件格式都可以用XML代替,而这一切只需要一个解析器。
最全面正确的说明可以在/TR/2004/REC-xml-20040204/找到,但坦白地说,它很晦涩难懂。
事实上我喜欢/xml/tutorial上关于XML的介绍。
有不同的方法可以访问和与XML数据进行交互。
TinyXML 使用文档对象模型(DOM),这意味着XML数据被解析成一个可被浏览和操作的C++对象,然后它可以被写到磁盘或者另一个输出流中。
你也可以把C++对象构造成一个XML文档然后把它写到磁盘或者另一个输出流中。
TinyXML被设计得容易快速上手。
什么是Tiny XML?TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux 中编译。
这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这棵XML树。
DOM模型即文档对象模型,是将整个文档分成多个元素(如书、章、节、段等),并利用树型结构表示这些元素之间的顺序关系以及嵌套包含关系。
TinyXML是个解析库,主要由DOM模型类(TiXmlBase、TiXmlNode、TiXmlAttribute、TiXmlComment、TiXmlDeclaration、TiXmlElement、TiXmlText、TiXmlUnknown)和操作类(TiXmlHandler)构成。
它由两个头文件(.h文件)和四个CPP文件(.cpp文件)构成,用的时候,只要将(tinyxml.h、tinystr.h、tinystr.cpp、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.cpp)导入工程就可以用它的东西了,这里我把这四个cpp文件做成了静态库libtinyxml.a,使用的时候只在工程中需包含静态库和两个头文件。
继承关系:XML也是有这几个对象组成了,一般来说我们经常使用的类如下:● TiXmlDocument:文档类,它代表了整个xml文件。
● TiXmlDeclaration:声明类,它表示文件的声明部分,如上图所示。
● TiXmlComment:注释类,它表示文件的注释部分,如上图所示。
● TiXmlElement:元素类,它是文件的主要部分,并且支持嵌套结构,一般使用这种结构来分类的存储信息,它可以包含属性类和文本类,如上图所示。
如何析xml文档,一般是这样的:1 加载xml2 获得根元素3 获取任意一个元素4 对元素进行解析。
1加载xml加载xml首先必须得创建一个文档对象,文档类有下面几种构造函数TiXmlDocument();//Create a document with a name. The name of the document is also the filename of the xml.TiXmlDocument( const char * documentName );●通过文件载入有了文档对象后可以载入文件,载入文件的函数原型为bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );●通过字符串载入也可以通过载入xml字符串,函数原型为:virtual const char* Parse( const char* p, TiXmlParsingData* data = 0,TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );TiXmlParsingData* data 这个参数不知道有什么用,默认使用了没问题例如:TiXmlDocument doc();doc.Prase("<xml version=\"1.1\" ><a><n a=\"a\" /></a></xml>");●文档对象的四个成员函数void Print() const输出到控制台窗口bool SaveFile( const std::string& filename ) const;保存文档到指定文件名const char * ErrorDesc() const; //用来输出错误说明int ErrorId()const ; //用来输出错误ID2 获得根元素通过上一步加载的文档对象来获取跟元素,下面是获取根元素的函数原型:TiXmlElement* RootElement() ;doc.RootElement();//通过文档对象获取跟元素;3 获取任意一个元素通过上一步获取的根元素对象可以获取文档中的任意一个元素对象,主要通过以下函数:下面两个函数,返回第一个子元素。
//注这里首先要安装mini XML相关的库#include<stdio.h>#include<mxml.h>#include<time.h>#include<stdlib.h>typedef struct _date{int year;int mon;int day;}Date;int make_xml(char *mxml_buf,int len){time_t tt;char year[4] = {0};char mon[2] = {0};char day[2] = {0};memset(mxml_buf,0,len);mxml_node_t *root = NULL;mxml_node_t *tree = NULL;mxml_node_t *node1 = NULL;tt = time(0);struct tm *tm = localtime(&tt);sprintf(year,"%d",tm->tm_year+1900);sprintf(mon,"%d",tm->tm_mon+1);sprintf(day,"%d",tm->tm_mday);tree = mxmlLoadString(NULL,"<?xml version=\"1.0\"?>",MXML_TEXT_CALLBACK);// tree = mxmlNewXML("1.0");root = mxmlNewElement(tree,"DATA");node1 = mxmlNewElement(root,"YEAR");mxmlNewTextf(node1,0,"%s",year);node1 = mxmlNewElement(root,"MONTH");mxmlNewTextf(node1,0,"%s",mon);node1 = mxmlNewElement(root,"DAY");mxmlNewTextf(node1,0,"%s",day);mxmlSaveString(tree,mxml_buf,len,MXML_NO_CALLBACK);FILE *fp;fp = fopen("filename.xml", "w+");mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);fclose(fp);mxmlDelete(tree);return 0;}int find_mxml(Date *data_t,char *buf){char mxml_buf[1024]={0};strncpy(mxml_buf,buf,1024);mxml_node_t *tree = NULL;mxml_node_t *root = NULL;mxml_node_t *node1 = NULL;tree = mxmlLoadString(NULL,mxml_buf,MXML_NO_CALLBACK);if(tree == NULL){printf("tree is null!\n");return -1;}root = mxmlFindElement(tree,tree,"DATA",NULL,NULL,MXML_DESCEND);if(root == NULL){printf("find node DA TA ERR!\n");return -1;}node1 = mxmlFindElement(root,tree,"YEAR",NULL,NULL,MXML_DESCEND);if(node1 == NULL){printf("find node YEAR ERR!\n");return -1;}data_t->year = atoi(node1->child->value.text.string);node1 = mxmlFindElement(root,tree,"MONTH",NULL,NULL,MXML_DESCEND);if(node1 == NULL){printf("find node MONTH ERR!\n");return -1;}data_t->mon = atoi(node1->child->value.text.string);node1 = mxmlFindElement(root,tree,"DAY",NULL,NULL,MXML_DESCEND);if(node1 == NULL){printf("find node DAY ERR!\n");return -1;}data_t->day = atoi(node1->child->value.text.string);return 0;}int main(){Date *data = (Date *)malloc(sizeof(Date));;char mxml_buf[1024];make_xml(mxml_buf,1024);printf("%s\n",mxml_buf);find_mxml(data,mxml_buf);printf("year:%d\nmon:%d\nday:%d\n",data->year,data->mon,data->day);return 0;}。
C语⾔读写XML⽂档:libmxml库初学笔记(Mini-XML)使⽤XML存取数据很⽅便。
官⽹有详尽的英⽂⼿册,这⾥还找到了⼀份中⽂⼿册:这⾥只放⾃⼰学习时写的测试代码,有兴趣的同学可以做个参考。
#include<mxml.h>//创建xml⽂档//声明创建 xml树需要的 node节点mxml_node_t* xml; // xml格式标记mxml_node_t* keys_n; // 词汇库,unkey-词汇主键的⽗节点mxml_node_t* unikey_n; //⼀条词汇记录的基本单元,mark-词汇标签和 explain-词汇释义的⽗节点mxml_node_t* elem_n; //创建 mark explain 的节点//在内存中通过挂载node节点,构建 xml treexml=mxmlNewXML("1.0");//创建xml⽂档格式标记,必须,xml tree的根keys_n=mxmlNewElement(xml, "keys");//新节点,名为keys,挂载到 xmlunikey_n=mxmlNewElement(keys_n, "unikey");//新节点,名为unikey,挂载到 keysmxmlElementSetAttr(unikey_n, "word", "go alpha");//为unikey_n的节点设置属性:word="go alpha"elem_n=mxmlNewElement(unikey_n, "elem");//新节点,名为elem, 挂载到unikeymxmlElementSetAttr(elem_n, "element", "mark");//为elem_n的节点设置属性:element="mark"mxmlNewText(elem_n, 0, "AI");//为elem_n的节点新增⽂本,⽂本前的whitespace(空格)个数为0,内容为”AI”elem_n=mxmlNewElement(unikey_n, "elem");//新节点,名为elem, 挂载到unikeymxmlElementSetAttr(elem_n, "element", "explain");//为elem_n的节点设置属性:element="explain"mxmlNewText(elem_n, 0, "Google的AI程序");//为elem_n的节点新增⽂本,⽂本前的whitespace(空格)个数为0//将内存中创建的节点树写⼊⽂件FILE *fp = fopen("/Users/yaou/Area/tmp/xmltest-1.xml", "w");mxmlSaveFile(xml, fp, MXML_NO_CALLBACK);//关闭⽂件fclose(fp);//释放内存中的节点树mxmlDelete(xml);之后⼿动在新⽂件xmltext-1.xml ⾥添加⾥⼀些节点。
TinyXml使用指南一、 TinyXml的特点TinyXml是一个基于DOM模型的、非验证的轻量级C++解释器。
1. SAX和DOM目前XML的解析主要有两大模型:SAX和DOM。
其中SAX是基于事件的,其基本工作流程是分析XML文档,当发现了一个新的元素时,产生一个对应事件,并调用相应的用户处理函数。
这种方式占用内存少,速度快,但用户程序相应得会比较复杂。
而DOM(文档对象模型),则是在分析时,一次性的将整个XML文档进行分析,并在内存中形成对应的树结构,同时,向用户提供一系列的接口来访问和编辑该树结构。
这种方式占用内存大,速度往往慢于SAX,但可以给用户提供一个面向对象的访问接口,对用户更为友好。
2. 验证和非验证对于一个特定的XML文档而言,其正确性分为两个层次。
首先是其格式应该符合XML的基本格式要求,比如第一行要有声明,标签的嵌套层次必须前后一致等等,符合这些要求的文件,就是一个合格的XML文件,称作well-formatted。
但除此之外,一个XML文档因其内容的不同还必须在语义上符合相应的标准,这些标准由相应的DTD 文件或者Schema文件来定义,符合了这些定义要求的XML文件,称作valid。
因此,解析器也分为两种,一种是验证的,即会跟据XML文件中的声明,用相应的DTD文件对XML文件进行校验,检查它是否满足DTD文件的要求。
另一种是忽略DTD文件,只要基本格式正确,就可以进行解析。
就我所知,验证的解析器通常都是比较重量级的。
TinyXml不支持验证,但是体积很小,用在解析格式较为简单的XML文件,比如配置文件时,特别的合适。
二、 TinyXml的构建和使用1. 获取TinyXml首页在/tinyxml/index.html,从这里可以找到最新版本的源代码,目前的版本是2.3.4。
2.构建TinyXml在构建时可以选择是否支持STL,选择的话,则可以使用std::string,所以通常应该打开这个选项。
TinyXML 指南这是什么?这份指南有一些关于如何有效地使用TinyXML的技巧和建议。
我也会尝试讲一些诸如怎样使字符串与整型数相互转化的C++技巧。
这与TinyXML本身没什么关系,但它也许会对你的项目有所帮助,所以我还是把它加进来了。
如果你不知道基本的C++概念,那么这份指南就没什么用了。
同样的,如果你不知道什么是DOM,那先从其它地方找来看看吧。
在我们开始之前一些将会被用到的XML数据集/文件。
example1.xml:<?xml version="1.0" ?><Hello>World</Hello>example2.xml:<?xml version="1.0" ?><poetry><verse>AlasGreat WorldAlas (again)</verse></poetry>example3.xml:<?xml version="1.0" ?><shapes><circle name="int-based" x="20" y="30" r="50" /><point name="float-based" x="3.5" y="52.1" /></shapes>example4.xml:<?xml version="1.0" ?><MyApp><!–Settings for MyApp –><Messages><Welcome>Welcome to MyApp</Welcome><Farewell>Thank you for using MyApp</Farewell></Messages><Windows><Window name="MainFrame" x="5" y="15" w="400" h="250" /></Windows><Connection ip="192.168.0.1" timeout="123.456000" /></MyApp>开始把文件加载成XML把一个文件加载成TinyXML DOM的最简单方法是:TiXmlDocument doc( "demo.xml" );doc.LoadFile();一个更接近于现实应用的例子如下。
TinyXML中文文档六月08TinyXML中文文档TinyXML No Comments »完整显示 1 2 3 4 5 6 7  译注:本文是TinyXML 2.5.2版本Document的中文文档,经原作者Lee Thomason同意由hansen翻译,如有误译或者错漏,欢迎指正。
版权:版权归原作者所有,翻译文档版权归本人hansen所有,转载请注明出处。
原文:/tinyxmldocs/index.html 0;TinyXml 文档2.5.2TinyXMLTinyXML是一个简单小巧,可以很容易集成到其它程序中的C++ XML解析器。
它能做些什么简单地说,TinyXML解析一个XML文档并由此生成一个可读可修改可保存的文档对象模型(DOM)。
XML的意思是“可扩展标记语言“(eXtensible Markup Language)。
它允许你创建你自己的文档标记。
在为浏览器标记文档方面HTML做得很好,然而XML允许你定义任何文档标记,比如可以为一个组织者应用程序定义一个描述“to do”列表的文档。
XML拥有一个结构化并且方便的格式,所有为存储应用程序数据而创建的随机文件格式都可以用XML代替,而这一切只需要一个解析器。
最全面正确的说明可以在/TR/2004/REC-xml-20040204/找到,但坦白地说,它很晦涩难懂。
事实上我喜欢/xml/tutorial上关于XML的介绍。
有不同的方法可以访问和与XML数据进行交互。
TinyXML 使用文档对象模型(DOM),这意味着XML数据被解析成一个可被浏览和操作的C++对象,然后它可以被写到磁盘或者另一个输出流中。
你也可以把C++对象构造成一个XML文档然后把它写到磁盘或者另一个输出流中。
TinyXML被设计得容易快速上手。
开源TinyXML最简单的新⼿教程TinyXML它是基于⼀个⾮常受欢迎的现在DOM型号XML解析器,简单易⽤且⼩巧玲珑,很适合存储简单数据。
配置⽂件。
该项⽬属于开源项⽬,在sourceforge上边的链接是:当前最新版本号是2.6.2先看⼀下源代码⽂档的结构:Docs是帮助⽂档。
⾥边有许多的使⽤说明,只截⼀张图看⼀下:详细依据须要再看我们使⽤的是它的库。
能够是静态的也能够是动态库。
我就⽤静态库了,将这⾥边的⼏个头⽂件和源⽂件⼀起创建⼀个project,⽣成Lib库:tinyxml.lib使⽤的时候,将这两个头⽂件以及⽣成的静态库加进去:⼀个简单的样例#include <iostream>using namespace std;#ifdef TIXML_USE_STL#include <iostream>#include <sstream>using namespace std;#else#include <stdio.h>#endif#if defined( WIN32 ) && defined( TUNE )#include <crtdbg.h>_CrtMemState startMemState;_CrtMemState endMemState;#endif#include "tinyxml/tinyxml.h"int main(){TiXmlDocument *pDoc = new TiXmlDocument;if (NULL==pDoc){return false;}TiXmlDeclaration *pDeclaration = new TiXmlDeclaration("1.0","gb2312","");if (NULL==pDeclaration){return false;}pDoc->LinkEndChild(pDeclaration);// ⽣成⼀个根节点TiXmlElement *pRootEle = new TiXmlElement("索引数据包信息");pDoc->LinkEndChild(pRootEle);//头节点TiXmlElement *pHeader = new TiXmlElement("头节点");pRootEle->LinkEndChild(pHeader);TiXmlElement *pCellNode = new TiXmlElement("字段1");pHeader->LinkEndChild(pCellNode);pCellNode->SetAttribute("str1","1状态");pCellNode->SetAttribute("str2","0状态");pDoc->SaveFile("d:\\result.xml");return 0;}结果:临时这⾥边的字符串不能是宽字符的。
tinyxml使用文档TinyXML是一个用于解析和生成XML文档的C++库。
它提供了简单而高效的API,使得在C++中处理XML变得容易。
本文将介绍TinyXML的基本使用方法,包括XML的解析、创建和修改。
1. 引入TinyXML库2.解析XML文档要解析XML文档,可以使用TinyXML提供的XMLDocument类。
首先,需要创建一个XMLDocument对象,并通过调用其LoadFile(方法加载XML 文件。
以下是一个解析XML文档的示例:```cpp#include "tinyxml.h"int mainTiXmlDocument doc;if (doc.LoadFile("example.xml"))TiXmlElement* root = doc.RootElement(;if (root)//处理根元素//...}}return 0;```在上面的示例中,首先创建一个XMLDocument对象,并通过调用LoadFile(方法加载名为"example.xml"的XML文件。
然后,通过调用RootElement(方法获取根元素,并进行进一步处理。
3.遍历XML元素要遍历XML元素,可以使用TiXmlElement类的NextSiblingElement(和FirstChildElement(方法。
NextSiblingElement(方法返回下一个同级元素,而FirstChildElement(方法返回第一个子元素。
以下是一个遍历XML元素的示例:```cppTiXmlElement* element = root->FirstChildElement(;while (element)//处理元素//...element = element->NextSiblingElement(;```在上面的示例中,首先通过调用FirstChildElement(方法获取第一个子元素,然后使用一个循环遍历所有同级元素。
TinyXML入门教程 1什么是XML? 1文档类 2创建文档对象 3输出文档对象 3保存文档对象 4返回第一个根元素 5声明类 5注释类 6元素类 6节点名 6父节点 6子节点 7编辑子节点 7同级节点 7遍历元素 8元素属性 8元素函数总结 9属性类 10文章下载源代码下载什么是XML?XML全称EXtensible Markup Language,翻译为可扩展标记语言,简而言之就是你可以自定义数据的标识,以此来区分各种不同的数据,以便于进行数据交换,例如html就可以理解为一种简单的xml语言。
XML文件通常就是一个文本文件,可以使用任何编码上图就是我系统中一个xml文件的图标,使用VC2005打开它,你可以看到如下内容:XML也是有这几个对象组成了,一般来说我们经常使用的类如下:l TiXmlDocument:文档类,它代表了整个xml文件。
l TiXmlDeclaration:声明类,它表示文件的声明部分,如上图所示。
l TiXmlComment:注释类,它表示文件的注释部分,如上图所示。
l TiXmlElement:元素类,它是文件的主要部分,并且支持嵌套结构,一般使用这种结构来分类的存储信息,它可以包含属性类和文本类,如上图所示。
n TiXmlAttribute/TiXmlAttributeSet:元素属性,它一般嵌套在元素中,用于记录此元素的一些属性,如上图所示。
n TiXmlText:文本对象,它嵌套在某个元素内部,如上图所示。
TinyXml使用文档对象模型(DOM)来解析xml文件,这种模型的处理方式为在分析时,一次性的将整个XML文档进行分析,并在内存中形成对应的树结构,同时,向用户提供一系列的接口来访问和编辑该树结构。
这种方式占用内存大,但可以给用户提供一个面向对象的访问接口,对用户更为友好,非常方便用户使用。
下面我们依次来介绍各个类的用法。
文档类文档类代表一个XML文档,通过它,你可以保存,载入和打印输出文档。
TinyXml使用说明1. 安装和引入TinyXml库2.创建XML文档使用TinyXml,你可以创建一个XML文档对象。
首先,包含头文件`tinyxml.h`。
```cpp#include "tinyxml.h"```然后,通过使用 `TiXmlDocument` 类来创建一个XML文档对象。
```cppTiXmlDocument doc;```3.加载和保存XML文档一旦你创建了一个XML文档对象,你就可以加载一个XML文件或字符串,并将其保存为XML文件。
-加载XML文件:```cppbool loadSuccess = doc.LoadFile("example.xml");if (loadSuccess)//文件加载成功,可以对其进行处理} else//文件加载失败,进行错误处理}```-加载XML字符串:```cppconst char* xmlString ="<root><element>value</element></root>";bool loadSuccess = doc.Parse(xmlString);if (loadSuccess)//字符串解析成功,可以对其进行处理} else//字符串解析失败,进行错误处理}```-保存XML文档:```cppdoc.SaveFile("output.xml");```4.获取XML元素使用TinyXml,你可以获取XML文档中的元素和属性。
首先,你需要获取XML文档的根元素。
```cppTiXmlElement* root = doc.RootElement(;```接下来,你可以使用 `TiXmlElement` 类的成员函数来获取元素的名称、值和属性。
-获取元素的名称和值:```cppconst char* elementName = root->Value(;const char* elementValue = root->GetText(;```-获取元素的属性:```cppconst char* attributeName = root->Attribute("name");```5.遍历XML元素使用TinyXml,你可以遍历XML文档中的元素和属性,并对其进行处理。
mini-xml编译
编译Mini-XML(mxml)库通常涉及以下步骤:
1. 获取源代码:首先,你需要从Mini-XML 的官方网站或代码托管平台(如GitHub)上获取源代码。
通常,你可以通过Git 克隆仓库或下载压缩包的方式获取源代码。
2. 检查依赖项:Mini-XML 可能有一些依赖项,例如CMake(用于构建过程)等。
确保你的系统中安装了这些依赖项。
3. 配置构建:进入源代码目录,在命令行中执行以下步骤:
```bash
mkdir build
cd build
cmake ..
```
这将创建一个名为`build` 的目录,进入其中并配置构建过程。
CMake 会生成用于你系统的构建文件。
4. 执行构建:在同样的`build` 目录中执行以下命令:
```bash
make
```
这将编译Mini-XML 库。
你也可以使用其他构建工具,具体取决于项目的配置。
5. 安装(可选):如果你想在系统中全局安装Mini-XML,可以执行以下命令:
```bash
sudo make install
```
这将把Mini-XML 安装到默认的系统路径中。
6. 测试(可选):通常,项目会附带一些测试用例。
你可以执行这些测试用例,确保库在你的系统上正常运行:
```bash
make test
```
这些步骤是通用的构建过程,但具体的步骤可能因Mini-XML 版本和你的操作系统而有所不同。
确保查阅Mini-XML 的文档(通常在项目的README 文件中)以获取详细的构建说明。
xml规范(1)Extensible Markup Language (XML) 1.0本文档是W3C建议XML 1.0的中文版,其中可能有错误和不妥之处。
英文版是唯一的正式版,位于:http:///TR/1998/REC-xml-19980210http:///TR/REC-xml/本文档位于:http:///~qqiu/xml/trans/REC-xml-19980210-cn.html著作权声明位于:http:///Consortium/Legal/copyright-documents.htmlCopyright ? 1998 W3C (MIT,INRIA,Keio ),All Rights Reserved. W3C liability,trademark,document use and software licensing rules apply.REC-xml-19980210-cn可扩展标记语言(XML) 1.0W3C建议1998年2月10日本版本:http:///TR/1998/REC-xml-19980210http:///TR/1998/REC-xml-19980210.xmlhttp:///TR/1998/REC-xml-19980210.htmlhttp:///TR/1998/REC-xml-19980210.pdfhttp:///TR/1998/REC-xml-19980210.ps最新版本:http:///TR/REC-xml上一版本:http:///TR/PR-xml-971208编者:TimBray(TextualityandNetscape)<********************>JeanPaoli(Microsoft)<********************>C.M.Sperberg-McQueen(UniversityofIllinoisatChicago)<**************>摘要本文档完整地描述了可扩展标记语言(Extensible Markup Language,XML),它是标准通用标记语言(Standard Generic Markup Language,SGML)的一个子集。
TinyXML解析TinyXML介绍最近做⼀个负载均衡的⼩项⽬,需要解析xml配置⽂件,⽤到了TinyXML,感觉使⽤起来很容易,给出⼀个使⽤TinyXML进⾏XML解析的简单例⼦,很多复杂的应⽤都可以基于本例⼦的⽅法来完成。
TinyXML是⼀个开源的解析XML的解析库,能够⽤于C++,能够在Windows或Linux中编译。
这个解析库的模型通过解析XML⽂件,然后在内存中⽣成DOM模型,从⽽让我们很⽅便的遍历这棵XML树。
DOM模型即⽂档对象模型,是将整个⽂档分成多个元素(如书、章、节、段等),并利⽤树型结构表⽰这些元素之间的顺序关系以及嵌套包含关系。
TinyXML类说明在TinyXML中,根据XML的各种元素来定义了⼀些类:TiXmlBase:整个TinyXML模型的基类。
TiXmlAttribute:对应于XML中的元素的属性。
TiXmlNode:对应于DOM结构中的节点。
TiXmlComment:对应于XML中的注释。
TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0" ?>。
TiXmlDocument:对应于XML的整个⽂档。
TiXmlElement:对应于XML的元素。
TiXmlText:对应于XML的⽂字部分。
TiXmlUnknown:对应于XML的未知部分。
TiXmlHandler:定义了针对XML的⼀些操作。
下载和编译⼯作⽬录为:tinyxml/ //⼯作⽬录|-- include //头⽂件根⽬录| |-- tinyxml //tinyxml头⽂件,包括tinystr.h tinyxml.h|-- src //cpp源码⽂件根⽬录 |-- tinyxml //tinyxml源码⽂件夹,包括tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp |-- main.cpp //我们的主函数,调⽤tinyxml的⽰例代码|-- conf //我们⽰例中⽤的xml⽂件所在的⽂件夹|-- makefile //makefile,不⽤我们多说了吧,不懂请看我博客的makefile最佳实践简单的例⼦在conf⽬录下建⽴student.xml代码<School name="软件学院"><Class name = "C++"><Student name="tinyxml" number="123"><email>tinyxml@</email><address>中国</address></Student><Student name="jsoncpp" number="456"><email>jsoncpp@</email><address>美国</address></Student></Class></School>想要使⽤tinyxml,只需要在头⽂件中包含<tinyxml.h>即可读取整个xml⽂件并打印代码:void printSchoolXml() {using namespace std;TiXmlDocument doc;const char * xmlFile = "conf/school.xml";if (doc.LoadFile(xmlFile)) {doc.Print();} else {cout << "can not parse xml conf/school.xml" << endl;}}读取XMLvoid readSchoolXml() {using namespace std;const char * xmlFile = "conf/school.xml";TiXmlDocument doc;if (doc.LoadFile(xmlFile)) {doc.Print();} else {cout << "can not parse xml conf/school.xml" << endl;return;}TiXmlElement* rootElement = doc.RootElement(); //School元素TiXmlElement* classElement = rootElement->FirstChildElement(); // Class元素TiXmlElement* studentElement = classElement->FirstChildElement(); //Studentsfor (; studentElement != NULL; studentElement = studentElement->NextSiblingElement() ) {TiXmlAttribute* attributeOfStudent = studentElement->FirstAttribute(); //获得student的name属性for (;attributeOfStudent != NULL; attributeOfStudent = attributeOfStudent->Next() ) {cout << attributeOfStudent->Name() << " : " << attributeOfStudent->Value() << std::endl;}TiXmlElement* studentContactElement = studentElement->FirstChildElement();//获得student的第⼀个联系⽅式for (; studentContactElement != NULL; studentContactElement = studentContactElement->NextSiblingElement() ) { string contactType = studentContactElement->Value();string contactValue = studentContactElement->GetText();cout << contactType << " : " << contactValue << std::endl;}}}写⼊xmlvoid writeSchoolXml() {using namespace std;const char * xmlFile = "conf/school-write.xml";TiXmlDocument doc;TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");TiXmlElement * schoolElement = new TiXmlElement( "School" );TiXmlElement * classElement = new TiXmlElement( "Class" );classElement->SetAttribute("name", "C++");TiXmlElement * stu1Element = new TiXmlElement("Student");stu1Element->SetAttribute("name", "tinyxml");stu1Element->SetAttribute("number", "123");TiXmlElement * stu1EmailElement = new TiXmlElement("email");stu1EmailElement->LinkEndChild(new TiXmlText("tinyxml@") );TiXmlElement * stu1AddressElement = new TiXmlElement("address");stu1AddressElement->LinkEndChild(new TiXmlText("中国"));stu1Element->LinkEndChild(stu1EmailElement);stu1Element->LinkEndChild(stu1AddressElement);TiXmlElement * stu2Element = new TiXmlElement("Student");stu2Element->SetAttribute("name", "jsoncpp");stu2Element->SetAttribute("number", "456");TiXmlElement * stu2EmailElement = new TiXmlElement("email");stu2EmailElement->LinkEndChild(new TiXmlText("jsoncpp@"));TiXmlElement * stu2AddressElement = new TiXmlElement("address");stu2AddressElement->LinkEndChild(new TiXmlText("美国"));stu2Element->LinkEndChild(stu2EmailElement);stu2Element->LinkEndChild(stu2AddressElement);classElement->LinkEndChild(stu1Element);classElement->LinkEndChild(stu2Element);schoolElement->LinkEndChild(classElement);doc.LinkEndChild(decl);doc.LinkEndChild(schoolElement);doc.SaveFile(xmlFile);}XML删除操作删除某个节点, TiXmlNode是TiXmlElement、TiXmlComment、TiXmlText、TiXmlDeclaration、TiXmlUnknown、TiXmlDocument的基类TiXmlNode node;node.Clear();从A节点上移除⼦节点BTiXmlNode nodeA;nodeA. RemoveChild( TiXmlNode* removeThis );从元素A上移除名字为B的属性TiXmlAttribute attrA;attrA. RemoveAttribute( const char * name );XML修改操作查找内容为<mfid val="1234" />,现需要将1234改成其他值TiXmlNode* lpnode = NULL;lpnode = tixml.RootElement()->IterateChildren("mfid",lpnode);TiXmlAttribute* tiattr = lpnode->ToElement()->FirstAttribute();//找到mfid节点,获取第⼀个属性值。
自己所在的项目组中,读取xml 配置文件使用的是tinyxml,所以对tinyxml 用法熟些。
当为自己的代码选择xml 解析库时,搜索得知rapidxml 是一个不错的选择,小巧,快速,作者还和strlen 作过对比:Platform Compiler strlen() RapidXml pugixml 0.3 pugxml TinyXml Pentium 4 MSVC 8.0 2.5 5.4 7.0 61.7 298.8 Pentium 4 gcc 4.1.1 0.8 6.1 9.5 67.0 413.2 Core 2 MSVC 8.0 1.0 4.5 5.0 24.6 154.8 Core 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 Pentium 3 MSVC 8.0 2.0 6.3 7.0 30.9 211.9 Pentium 3 gcc 4.1.1 1.0 6.7 8.9 35.3 316.0可见确实不错。
关于如何保持这么高的效率,RAPIDXML Manual中提到:∙In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.∙Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.∙Extensive use of lookup tables for parsing.∙Hand-tuned C++ with profiling done on several most popular CPUs.包含文件:rapidxml.hpp:实现内存池解析string 异常处理,包含:∙xml_base 基数节点类∙xml_attribute 文本类∙xml_node 节点类xml_document 文档类rapidxml_iterators.hpp:提供两个迭代器类:node_iterator,attribute_iteratorrapidxml_print.hpp:提供跟字符串,流对象的装换函数rapidxml_utils.hpp:提供一个file用来读取文件使用,跟两个计数函数count_children,count_attributes随便写个文件测试一下,xml 文件:[xml]<?xml version="1.0" encoding="GB2312"?><!--test--><TestUnit><PointPos><pos xy="100,200" xz="200,300"/><name name="三角形上的点"/></PointPos><item strName="hello world!"/></TestUnit>[/xml]代码:[c]#include <iostream>#include "rapidxml.hpp"#include "rapidxml_print.hpp"using namespace std;using namespace rapidxml;int main(){FILE* fp = fopen("test.xml", "r");if (! fp)return 1;//获取文件长度fseek(fp, 0, SEEK_END);size_t len = ftell(fp);fseek(fp, 0, SEEK_SET);//读取文件char* pBuf = new char[len+1];if (! pBuf)return 1;memset(pBuf, 0, len+1);fread(pBuf, len, 1, fp);fclose(fp);//开始解析xml_document<> doc;doc.parse<0>(pBuf);std::cout << doc;cout << "first node is: " << doc.first_node()->name() << "\n"; xml_node<>* node = doc.first_node("T estUnit"); //根节点if (node) {//TestUnit节点xml_node<>* PointPos = node->first_node("PointPos");cout << PointPos->name() << "\n";if (PointPos) {xml_node<>* pPos = PointPos->first_node("pos");if (pPos) {xml_attribute<>* pxy = pPos->first_attribute("xy");cout << pxy->name() << ":" << pxy->value() <<"\n";xml_attribute<>* pxz = pPos->first_attribute("xz");cout << pxz->name() << ":" << pxz->value() <<"\n";}xml_node<>* name = PointPos->first_node("name");if (name) {xml_attribute<>* pName = name->first_attribute("name");cout << pName->name() << ":" << pName->value() << "\n";}}//item节点xml_node<>* helloworld = node->first_node("item");cout << helloworld->name() << "\n";xml_attribute<>* phelloStr = helloworld->first_attribute("strName");cout << phelloStr->name() << ":" << phelloStr->value() << "\n";}delete [] pBuf;return 0;}[/c]运行结果:注意:代码24行传递默认解析参数0,当解析完毕后,pBuf里面的文本已经被改变了!添加如下代码将其打印出来:[c]for (size_t i = 0; i < len; i++) {char ch = *(pBuf + i);cout << ch;}[/c]结果是:这就不难看出,rapidxml 的In-situ parsing 的含义了!这一点,Manual说得很清楚,择录如下:3.3 Destructive Vs Non-Destructive ModeBy default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects: ∙no whitespace normalization is done∙no entity reference translation is done∙names and values are not zero-terminated, you must use xml_base::name_size() and xml_base::value_size() functions to tell where they end我们可以将解析代码替换为:doc.parse<parse_non_destructive>(pBuf),这样就可以不改变source text,只不过这时候,你得调用name_size() 或value_size() 来决定你想要获取的字符串的长度,因为rapidxml 仅仅是保存指针而已。
Mini-XML 入门这一章描述了如何写一个程序使用Mini-XML来访问XML文件中的数据.Mini-XML提供了以下功能:•在内存中创建和管理XML文档的函数.•读UTF-8和UTF-16 编码的XML文件和字符串.•写UTF-8 编码的XML文件和字符串.•支持任意的元素名称,属性以及属性值,没有任何其他限制,仅受限于有效内存.•支持整形、浮点、自定义("CDA TA")和文本数据类型在"叶"节点.•提供"查找"、"索引"、以及"步进"函数可以很简单的访问XML文档中的数据.Mini-XML 不进行基于"XML方案(SCHEMA)"文件或者其他内容源定义信息的校验和其他类型的处理,也不支持其他组织所要求的XML规范.基础知识Mini-XML 提供的一个你需要包含的头文件:#include <mxml.h>把Mini-XML库连接到你的应用程序使用-lmxml 选项:gcc -o myprogram myprogram.c -lmxml ENTER如果你已经安装pkg-config(1) 软件, 你可以使用它来为你的安装确定适当的编译和连接选项:pkg-config --cflags mxml ENTERpkg-config --libs mxml ENTER节点每一块XML文件中的信息片断(元素、文本、数字)是一个存储在内存中的"节点(nodes)" .节点使用mxml_node_t结构进行定义. 它的type成员变量定义了节点类型(element, integer,.译者:节点类型定义枚举参见:mxml_type_e。
析器有些不同,其中整数、浮点、和文本节点是指在一个XML元素中一系列的使用空格作为分割的值,每个元素可以拥有多个以上节点,并可以选择使用空格分开,如:<abc>aa bb cc</abc>,Mini-MXML在使用参数:MXML_TEXT_CALLBACK进行载入时,将在abc元素下面生成3个text类型的子节点。
在创建时也可以使用同样的方式创建节点。
整数和浮点也是同样方式,但如果转换失败则MiniXML报错。
而不透明字符串类型(OPAQUE) 则不进行字符串分割,在载入时需要使用MXML_OPAQUE_CALLBACK参数,将所有字符串形成一个子节点。
详情见:使用加载回调函数。
Z.F每一个节点总是有一个成员变量:user_data 可以允许你为每一个节点关联你需要的应用数据.新的节点可以使用以下函数进行创建mxmlNewElement, mxmlNewInteger, mxmlNewOpaque, mxmlNewReal, mxmlNewText mxmlNewTextf mxmlNewXML . 只有elements 可以拥有子节点,顶级节点必须是一个element , 通常是<?xml version="1.0"?> 使用mxmlNewXML()函数创建的节点.每个节点都有一些关联节点的指针,上(parent), 下(child), 左(prev), and 右(next) 相对应于当前节点. 如果你有一个XML文件如下所示:<?xml version="1.0"?><data><node>val1</node><node>val2</node><node>val3</node><group><node>val4</node><node>val5</node><node>val6</node></group><node>val7</node><node>val8</node></data>那么在内存中的文件节点树看上去如下所示:?xml|data|node - node - node - group - node - node| | | | | |val1 val2 val3 | val7 val8|node - node - node| | |val4 val5 val6这里"-"指向下一个节点,"|"指向第一个子节点。
当你使用完毕这些XML数据后,使用函数mxmlDelete来释放指定节点或者整个XML树节点和它下面所有子节点的内存:mxmlDelete(tree);创建XML 文档你可以在内存中创建和更新XML文档,使用mxmlNew 一系列函数. 下面的代码将创建上一章描述的XML文档:mxml_node_t *xml; /* <?xml ... ?> */mxml_node_t *data; /* <data> */mxml_node_t *node; /* <node> */mxml_node_t *group; /* <group> */xml = mxmlNewXML("1.0");data = mxmlNewElement(xml, "data");node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val1");node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val2");node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val3");group = mxmlNewElement(data, "group");node = mxmlNewElement(group, "node");mxmlNewText(node, 0, "val4");node = mxmlNewElement(group, "node");mxmlNewText(node, 0, "val5");node = mxmlNewElement(group, "node");mxmlNewText(node, 0, "val6");node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val7");node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val8");我们首先使用mxmlNewXML函数来创建所有XML文件都需要的标头<?xml version="1.0"?> :xml = mxmlNewXML("1.0");然后我们使用mxmlNewElement函数来创建本文件使用的<data>节点.第一个参数指定了父节点(xml) ,第二个参数是元素名(data):data = mxmlNewElement(xml, "data");每个在本文件中<node>...</node>之间的部分使用函数mxmlNewElement和mxmlNewText 来创建. mxmlNewText 的第一个参数指定了父节点(node).第二个参数指定了是否在文本之前添加空白字符,在本例中使用0或者false.最后一个参数指定了需要添加的实际文本: node = mxmlNewElement(data, "node");mxmlNewText(node, 0, "val1");在内存中的XML结果可以被保存或者进行其他处理,就像一个从磁盘或者字符串中读取的文档一样.加载XML你可以加载一个XML文件使用函数mxmlLoadFile :FILE *fp;mxml_node_t *tree;fp = fopen("filename.xml", "r");tree = mxmlLoadFile(NULL, fp,MXML_TEXT_CALLBACK);fclose(fp);第一个参数如果有的话则指定了一个存在的XML父节点.一般你将这个参数等于NULL,除非你想要连接多个XML源. 如果此参数等于NULL,那么指定的XML文件必须是一个完整的XML文档,文档头部要包含?xml元素.第二个参数指定了一个标准的文件流,使用fopen() 或者popen()进行打开. 你也可以使用stdin,如果你想要实现一个XML过滤器程序.第三个参数指定了一个回调函数用于一个新的XML元素节点直接返回的子节点的值类型: MXML_CUSTOM, MXML_IGNORE, MXML_INTEGER, MXML_OPAQUE, MXML_REAL, or MXML_TEXT. 加载回调函数的细节在第三章做了详细描述. 示例代码使用MXML_TEXT_CALLBACK 常量指定文档中所有的数据节点都包含使用以空格字符分割的文本的值. 其他标准的回调还有MXML_IGNORE_CALLBACK, MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, 和MXML_REAL_CALLBACK.函数mxmlLoadString可以从一个字符串中载入XML节点树:char buffer[8192];mxml_node_t *tree;...tree = mxmlLoadString(NULL, buffer,MXML_TEXT_CALLBACK);第一个和第三个参数和mxmlLoadFile()用法一样. 第二个参数指定了指定了字符串或者字符缓冲区用于加载XML,当父节点参数为NULL时内容必须为完整的XML文档,包括XML 头?xml元素.保存XML你可以保存XML文件使用mxmlSaveFile函数:FILE *fp;mxml_node_t *tree;fp = fopen("filename.xml", "w");mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);fclose(fp);第一个参数为想要保存的XML节点树,一般应该是一个指向你的XML文档顶级节点?xml 的节点指针.第二个单数是一个标准文件流,使用fopen() 或者popen()来打开. 你也可以使用stdout 如果你想要实现一个XML过滤器程序.第三个参数是一个空白回调函数用来控制保存文件时插入的"空白"字符."空白回调"的详细信息参见第三章. 以上的示例代码使用了MXML_NO_CALLBACK常量来指定不需要特别的空白处理.函数mxmlSaveAllocString, 和mxmlSaveString保存XML节点树到一个字符串中: char buffer[8192];char *ptr;mxml_node_t *tree;...mxmlSaveString(tree, buffer, sizeof(buffer),MXML_NO_CALLBACK);...ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK);第一个和最后一个参数的用法和函数mxmlSaveFile()一样. 函数mxmlSaveString 给出了一个指针和长度的参数来保存XML文档到一个固定大小的缓冲区中。