XML概述、语法及常用操作
1. XML概述
关于XML的定义有以下几种说法:
① XML是可扩展标记语言(Extensible Markup Language)的缩写。
② XML是一种类似于HTML的标记语言。
③ XML是描述数据的,重点描述“数据是什么”。
④ XML的标记不是在XML中预定义的,你必须定义自己的标记。
⑤ XML使用文档类型定义(DTD)或者模式(Schema)来描述数据。
⑥ XML使用DTD或者Schema后就是自描述语言。
⑦ XML数据和格式是分离的,XML文档本身不定义如何来显示数据。
⑧ XML并不只是标记语言,它只是用来创造标记语言(比如HTML)的元语言。
⑨ 不能用XML来直接写网页。即便是包含了XML数据,依然要转换成HTML格式才能在浏览器上显示。
⑩ XML可以交换数据、共享数据、存储数据、利用数据、创建新的语言。
2. XML和HTML的主要区别
XML和HTML的主要区别如下:
① XML不是HTML的替代品,XML和HTML是两种不同用途的语言。
② XML是被设计用来描述数据的。重点是:什么是数据,如何存放数据。
③ HTML是被设计用来显示数据的。重点是:显示数据以及如何更好地显示数据。
④ HTML是与显示信息相关的,XML则是与描述信息相关的。
⑤ HTML将数据和显示混在一起,而XML则将数据和显示分开来。
⑥ XML是元语言,HTML是具体的语言。XML可以定义一种新的语言,而HTML则不能。人们可以用XML语法定义出新的语言,如XML是WAP和WML语言的母亲。
3. XML与HTML的举例说明
XML可以用来描述数据,重点是“数据是什么”。 HTML则是用来显示数据,重点是“如何显示数据”。
HTML是一个定型的标记语言,它用固有的标记来描述、显示网页内容。比如,H1表示首行标题,有固定的尺寸。相对的,XML则没有固定的标记,不能描述网页具体的外观和内容,它只是描述内容的数据形式和结构。
在HTML里,有许多固定的标记,在使用时,不能使用HTML规范里没有的标记。而在XML中,你能建立任何你需要的标记。比如,你的文档里包含一些游戏的攻略,你可以建立一个名为的标记,然后在下再根据游戏类别建立、等标记。只要这些标记清晰,易于理解你可以建立任何数量的标记。
下面以test.html、test.xml来说明两者的不同。
test.html
A Simple HTML Example
HTML is Easy To Learn
Welcome to the world of HTML,This is the first paragraph.
test.xml
Lin
Ordm
Reminder
Don't forget me this weekend!
对test.html和test.xml的说明如下:
test.html中的html、head、 body、H1、P这些标记类型、含义及用法已经是明确的,固定的。HTML每一版本标记的类型、用法及含义由W3C进行公布,全世界遵守这个统一标准。
test.xml中的note、to、from、heading、body这些标记类型、含义及用法可以自行定义,通信的多方自行约定含义和约定解析。
如IE、firefox浏览器能根据HTML标记(如title、body)解析显示HTML文件。而在只有一个XML内容文件下,浏览器无法解析XML标记和内容。因为HTML标记语法语义已经确定,而XML标记要自己定义语法语义。
4. XML的使用
XML的使用场合如下:
① XML是被设计用来存储数据、携带数据和交换数据的。
② XML可以从HTML中分离数据。通过XML,可以在HTML文件之外存储数据。
③ XML用于交换数据。通过XML,可以在不兼容的系统之间交换数据。
④ 使用XML,可以在网络中交换电子商务信息。
⑤ XML可以用于共享数据。通过XML,纯文本文件可以用来共享数据。
⑥ XML可以充分利用数据。使用XML,你的数据可以被更多的用户使用。
⑦ XML可以用于创建新的语言,它是WAP和WML语言的母亲。
⑧ 如果开发者有足够的预见性,那么将来的应用程序都应该使用XML的形式来存储数据。
5. XML的优势
HTML是用来设计人机交流用的,对布局、外观方面很擅长,但缺乏对内容、也就是信息含义的表达。除了少数几个用来表达内容或文义的标签,如p、address、title、strong外,几乎全都是用来设计网页格式的。假设需要一个能将商品价格明确标示的price标签,HTML则无能为力。
XML和HTML的一大不同处,就在于在XML文件里,我们可以自由定义标签。定义出来的标签,可以按自己的意思充分地表达文件的内容,譬如可以定义name、bookinfo这样充分达意的标签。在XML中,只注重内容,这和HTML强调布局的做法不大相同。XML文件的内容和外观设计是完全分开的。外观变动时,XML文件完全不受影响。
同时,XML的自描述性有利于资料的交换和传递,商务往来的公司之间,用不着、也不需要知道对方内部是采用何种格式储存资料,大家都用XML来做中介格式即可。如此一来,某个系统内部的变更,并不会殃及和它交流往来的其他系统,因而XML提供了一层理想的缓冲。很多人认为,XML将是电子商务理想的格式标准。
XML除了上述描述数据的优势外,还具有如下几个优势:XML可以广泛的运用于Web的任何地方,XML可以满足网络应用的需求,使用XML将使编程更加简单,XML便于学习和创建,XML文件代码更清晰和便于阅读理解。
6. XML组成
XML由XML对象组成。XML对象可以是元素、属性、CDATA、附加内容、文本节点、注释和处理指令。XML对象又可分为包含“简单内容”和包含“复杂内容” 两类,有子节点的XML对象归入包含复杂内容的一类。如果XML对象是属性、注释、处理指令或文本节点之中的任何一个,我们就说它包含简单内容。
7. XSL
XSL是指可扩展样式表语言(EXtensible Stylesheet Language)。它用于将XML文档的内容转换成另一种形式的文档,转换后的文档能被一些应用软件更好的显示。XSL之于XML,就像CSS之于HTML。XML用于承载数据,而XSL则用于设置数据格式。XSL专门用于处理XML文档,并且遵循XML语法。因此,它只能在支持XML的应用程序中与XML结合使用。下图19-1画出了XSL与其他语言的层次关系。
图19-1 XSL树形层次图
XSL包括以下三部分。
① XSLT:XSLT是一种转换XML文档的语言,如将XML文档转换成HTML文档或PDF文档等。
② XPath:是在XML文档中查找定位信息的语言。
③ XSL-FO:一种用于格式化XML文档的语言。
XML语法
8. XML文档包含三个部分
① 一个XML文档声明。
② 一个关于文档类型的定义。
③ 用XML标记创建的内容。
下面以myfile.xml为例进行说明。
<?xml version="1.0" encoding="GB2312"?> XML轻松学习手册 ajie ajie@aolhoo.com 20010115 其中,第一行<?xml version="1.0"?>就是一个XML文档的声明,第二行说明这个文档是用myfile.dtd来定义文档类型的,第三行以下的语句就是内容主体部分。
9. XML文档术语
① 标记(Tag):用来定义元素名称和属性名称。在XML中,标记必须成对出现,将数据包围在中间。
② 元素(Element):由元素名称和元素内容组成。一个元素由一个标记来定义,包括开始和结束标识以及其中的内容。
③ 属性(Attribute):由属性名称和属性内容组成。属性是对元素进一步描述和说明,一个元素可以有多个属性。属性是一种为元素加入描述性信息的机制。
④ 元素的包含关系:元素(属性,子元素(属性,子元素))。
⑤ 空元素:没有内容的元素。书写格式为或。
⑥ 声明(Declaration):在所有XML文档的第一行都有一个XML声明。这个声明表示这个文档是一个XML文档,它表示遵循的是哪一个XML规范的版本。
⑦ DTD(文件类型定义):DTD是用来定义XML文档中元素、属性以及元素之间的关系。通过DTD文件可以检测XML文档结构是否正确,但建立XML文档并不一定需要DTD文件。
⑧ Well-formed XML(良好格式的XML):一个遵守XML语法规则,并遵守XML规范的文档称之为“良好格式”。
⑨ Valid XML(有效格式的XML):一个遵守XML语法规则,并遵守相应DTD文件规范的XML文档称为有效的XML文档。
⑩ XML文档举例说明。
<?xml version="1.0" standalone="yes" encoding="UTF-8"?>
ajie
上述XML文件中元素标记(即元素名称)为author,属性标记(即属性名称)为sex。元素author内容为ajie,该元素author的sex属性内容为female。第一行是XML声明。
10. 属性与子元素的比较
属性也可以改成子元素,改成子元素后易于扩充和编程,但减少了可读性。
下面两个文件中,第一个包含sex属性,第二个把属性sex改成了子元素。
Anna Smith female Anna Smith 属性的缺点有:属性不能包含多个值,子元素可以;属性不容易扩展,属性不能够描述结构,子元素可以;属性值很难通过DTD进行测试。 属性的优点是增加了文件的可读性,程序处理耗费的内存空间和时间比子元素少。 数据既可以存储在子元素中也可以存储在属性中。元数据(与数据有关的数据)应该以属性的方式存储,而数据本身应该以元素的形式存储。
11. XML文档的语法规则
XML文档的语法规则如下:
必须有XML声明语句。声明语句是文件的第一句,格式为<?xml version="1.0" standalone="yes/no" encoding="UTF-8"?>。声明的作用是告诉浏览器或者其他处理程序这个文档是XML文档。声明语句中的version表示文档遵守XML规范的版本,standalone表示文档是否附带DTD文件,encoding表示文档所用的语言编码,默认是UTF-8。
在XML文档中,所有的标记必须要有结束标记,包括空标记。
所有的XML文档必须有一个根元素,XML文档中的第一个元素就是根元素。
所有的XML文档都必须包含一个单独的标记来定义,所有的其他元素都必须成对在根元素中嵌套。XML文档有且只有一个根元素。所有的XML标记都必须嵌套合理。
属性值必须使用引号(包括双引号和单引号)。在XML中,元素的属性值没有引号引着是不符合规定的。
使用XML,空白将被保留。在XML文档中,空白部分不会被解析器自动删除。
使用XML,CR/LF被转换为LF。使用XML,新行总是被标识为LF(Line Feed,即换行)。
在XML中注释的语法基本上和HTML中的一样,如 。
XML标记都是大小写敏感的。
XML文档使用了自描述和简单的语法。
12 XML元素的语法
XML元素的语法规则如下:
① XML元素是可以扩展的,它们之间有关联。
② XML元素有简单的命名规则。
③ XML元素是可以扩展的,XML元素的可扩展决定了XML文档的可扩展。
④ XML元素是相互关联的,XML元素之间可以是父子关系和兄弟关系。
⑤ XML元素由元素名称和元素内容组成。XML元素可以有不同的内容。
⑥ 元素可以用来标记XML文件中的区段。XML元素拥有下列的格式:
Content
内容Content部分将会被包含在XML标记中。
⑦ 虽然XML标记通常包围住内容部分,但是也可以建立不含内容的元素,称为空(empty elements)元素。在XML中,空元素可以利用下面两种方式来呈现:
13. XML元素命名规则
XML元素的语法规则如下:
① 元素的名字可以包含字母、数字和其他字符。
② 元素的名字只能以字母和“_” (下画线)开头。
③ 元素的名字不能以XML(或者xml、Xml、xMl…)开头。
④ 元素的名字不能包含空格,中间不能包含“:”(冒号)。
14. 属性的语法
XML属性的语法规则如下:
① XML元素在开始标记处可以有元素属性。
② XML元素可以有属性,属性通常包含一些关于元素的额外信息。
③ 属性值必须用引号引着(单引号、双引号都可以使用,单引号中可以包含双引号)。
④ 通常可以用子元素代替属性。
⑤ XML属性定义格式如下:
why
代码中person是元素名称,sex是属性名称。
15 注释的语法
XML注释的语法格式如下:
<!-- 这里是注释信息 -->
16. 转义字符
不合法的XML字符必须替换为相应的实体然后才可以使用。
如果在XML文档中使用类似“<”的字符, 那么解析器将会出现错误,因为解析器会认为这是一个新元素的开始。所以不应该像下面这样书写代码:
if salary < 1000 then
为了避免出现这种情况,必须将字符“<”转换成实体,改写方法如下:
if salary < 1000 then
下表19-1是五个在XML文档中预定义好的实体。实体必须以符号“&”开头,以符号“;”结尾。注意只有“<”字符和“&”字符对于XML来说是严格禁止使用的。剩下的都是合法的,为了减少出错,使用实体是一个好习惯。
17. CDATA的语法
CDATA全称character data,翻译为字符数据。在标记CDATA下,所有的标记、实体引用都被忽略,而被XML处理程序一视同仁地当做字符数据看待。CDATA语法格式如下:
<![CDATA[这里放置需要显示的字符]]>
例如<![CDATA[ajie]]>在页面上显示的内容为“ajie”。
对CDATA的两点说明如下:
在XML文档中的所有文本都会被解析器解析,只有在CDATA部件之内的文本会被解析器忽略。
CDATA部件之间不能再包含CDATA部件(不能嵌套)。
18. Namespaces的语法
Namespaces翻译为命名空间。命名空间有什么作用呢?当在一个XML文档中使用多个DTD文件时,就会出现这样的矛盾:因为XML中标识都是自己创建的,在不同的DTD文件中,标识名可能相同但表示的含义不同,这就可能引起数据混乱。
命名空间说明标记属于哪一空间,避免相同命名引起的混乱问题。
Namespaces通过给标识名称加一个网址(URL)定位的方法来区别这些名称相同的标识。Namespaces同样需要在XML文档的开头部分进行声明。
下面例子命名空间是h,解析时用http://www.w3.org/TR/html4网址的DTD文件解析。
<h:table xmlns:h=“http://www.w3.org/TR/html4/”>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
19. entity的语法
entity翻译为“实体”。实体把文档中共同部分抽象出来,达到一次定义多次引用的目的。可以预先定义一个entity,然后在一个文档中多次调用。
使用entity的好处有下面两点:
① 它可以减少差错,文档中多个相同的部分只需要输入一遍就可以了。
② 它提高了维护效率。
XML定义了两种类型的entity。一种是普通entity,在XML文档中使用;另一种是参数entity,在DTD文件中使用。
entity的定义语法为:
定义好的entity在文档中的引用语法为:
&entity-name;
下文copyright.xml中定义了copyright实体并加以引用,其文件内容如下:
<?xml version="1.0" encoding="GB2312"?>
]>
XML
ajie
ajie@aolhoo.com
20010115
©right;
20. XML的结构化
XML促使文档结构化,所有的信息按某种关系排列。结构化就是为文档建立树形框架,使每一部分都紧密联系,形成一个整体。结构化有如下两个原则:
① 每一部分(每一个元素)都和其他元素有关联,关联的级数就形成了结构。
② 标识本身的含义与它描述的信息相分离。
21. XML的确认
符合语法的XML文档称为结构良好的XML文档,一个结构良好的XML文档应该使用正确的语法。
通过DTD验证的XML文档称为有效的XML文档,一个有效的XML文档应该遵守DTD的描述。
XML DTD定义了XML文档中可用的合法元素。
XML Schema(XML模式)是基于XML的DTD替代品,W3C使得DTD和Schema可以相互替代。
XML文档中发生错误将导致XML程序停止,所以语法正确时XML文档才能解析完成,即此文档是有效的XML文档。
22. DTD语法
DTD是“有效XML文档”的必须文件,通过DTD文件来定义文档中元素和标识的规则及相互关系。
(1)设置元素
元素是XML文档的基本组成部分,使用时需在DTD中定义一个元素,然后在XML文档中使用。元素在DTD中定义的语法格式为:
<!ELEMENT DESCRIPTION (#PCDATA, DEFINITION)*>
其中“<!ELEMENT” 是元素的声明,说明要定义的是一个元素,声明后面的“DESCRIPTION”是元素的名称,“(#PCDATA, DEFINITION)*>”则是该元素的使用规则。
(2)DTD元素定义规则表
下表19-2概要列出了DTD中元素定义的规则,DTD中定义的规则说明了元素可以包含的内容以及相互的关系。
(3)DTD定义举例说明
下面建立myfile.xml文件,然后在myfile.dtd中定义此文件的元素规则。
建立myfile.xml文件,文件内容如下:
<?xml version="1.0" encoding="GB2312"?> XML轻松学习手册 ajie
建立myfile.dtd文件,文件内容如下:
<!ELEMENT myfile (title, author)> <!ELEMENT title (#PCDATA)> <!ELEMENT author (#PCDATA)>
23 XML编码
对XML编码的建议如下:
① 使用一种支持Unicode编码格式的编辑器。
② 确信知道自己正在使用哪种编码格式。
③ 在XML文档中使用属性声明设置编码格式。
④ XML文档说明要以<?开始,以?>结束。
⑤ XML文档编码定义格式如下:
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="gb2312"?>
24. DOM树
DOM(Document Object Model,即文档对象模型)树是将XML文件或XML字符串在内存建立文档对象树,方便XML节点增删改查操作。
使用XML时,一般需要首先将XML文档读入内存形成DOM树,使之结构化,以便进一步操作。下图19-2画出了DOM树的节点种类及其层次关系,树中的每个 Document、Element、Text和Attr都是DOM节点。
使用DOM的基本规则为:不要使用DOM来遍历文档。只要可能,就使用XPath来查找节点或遍历文档。使用高级函数库使DOM更易于使用。
下面以bookstore.xml文件来说明DOM树,此文件内容如下:
Harry Potter J K. Rowling 2005 29.99
bookstore.xml文件中的根元素是bookstore,文档中的book元素都被包含在bookstore中,book元素有4个子元素,分别为title、 author、year、price。bookstore.xml形成DOM树如下图19-3所示。
25. XML术语
① XHTML - 可扩展HTML(Extensible HTML)
② XSL - 可扩展样式表语言(Extensible Style Sheet Language)
XSL由三部分组成: XML文档转换(XML Document Transformation ,又叫XSLT)、模式匹配语法(XPath)、格式化对象(XSL FO)。
③ XSLT - XML转换语言(XML Transformation)
XSLT是一种比CSS功能更强的语言,它可将XML文档转换成其他格式的文档。
④ XPath - XML匹配模式(XML Pattern Matching)
XPath是一种用于标识XML文档各个部分的语言,这是一种为了XSLT和 XPointer而设计出来的语言。
⑤ XPointer - XML指针语言(XML Pointer Language)
XML指针语言(The XML Pointer Language,XPointer),标识XML文档的内部结构,例如元素、属性、内容等。
⑥ XLink - XML链接语言(XML Linking Language)
链接语言(The XML Linking Language,XLink),允许在不同的XML资源之间建立链接关系。
⑦ DTD - 文档类型定义 (Document Type Definition)
DTD主要用于定义编写XML文档所使用的元素。
⑧ Namespaces - 命名空间
XML命名空间提供一种可以把元素、属性、命名和URL地址引用相互关联的方法。
⑨ DOM - 文档对象模型(Document Object Model)
DOM定义了XML文档的接口、属性和方法。
⑩ SAX - XML的简单API(Simple API for XML)
SAX是另一种读取和操作XML文档的编程接口(与DOM类似)。
⑪ Schema-中文称模式
与DTD不同,它本身也是基于XML。XML Schema同时还支持名称空间,能够定义比DTD更复杂的数据类型和结构。XML Schema内置支持一系列的简单数据类型,如字符串、小数和整数等,还可以定义元素出现的次数。因此XML Schema更适合以数据为中心的文档。
26、libxml的安装
一般如果在安装系统的时候选中了libxml开发库的话,系统会默认安装。如果没有安装,可以按如下步骤进行手工安装。
① 从xmlsoft站点或ftp(ftp.xmlsoft.org)站点下载libxml压缩包 (libxml2-xxxx.tar.gz)
② 对压缩包进行解压缩
tar xvzf libxml2-xxxx.tar.gz
③ 进入解压缩后的文件夹中运行如下命令完成安装
./configure
make
make install
也可以使用./configure --prefix=$HOME/xmllib指定安装目录,如果不指定目录默认安装在系统目录“/usr/local/include/libxml2”下。
安装完成后就可以使用简单的代码解析XML文件,包括本地和远程的文件。但是在编码上可能有一些问题,libxml默认只支持UTF-8编码,无论输入输出都是UTF-8,所以如果解析一个XML得到的结果都是UTF-8,如果需要输出GB2312或者其他编码,就需要iconv工具来做转码,安装iconv工具的方法如下:
① 下载libiconv压缩包(如libiconv-1.11.tar.gz)
② 对压缩包进行解压缩
tar xvzf libiconv-1.11.tar.gz
③ 进入解压缩后的文件目录,运行如下命令完成安装
./configure
make
make install
27. 创建XML文档
(1)创建一个XML文档非常简单,其流程如下:
① 用xmlNewDoc函数创建一个文档指针doc。
② 用xmlNewNode函数创建一个节点指针root_node。
③ 用xmlDocSetRootElement将root_node设置为doc的根结点。
④ 给root_node添加一系列的子节点,并设置子节点的内容和属性。
⑤ 用xmlSaveFile将XML文档存入文件。
⑥ 用xmlFreeDoc关闭文档指针,并清除本文档中所有节点动态申请的内存。
有多种方式可以添加子节点,如可以用xmlNewTextChild直接添加一个文本子节点。也可以先创建新节点,然后用xmlAddChild将新节点加入到上层节点中。
(2)创建xml文件举例
CreateXmlFile.c源代码如下:
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
int main()
{//定义文档和节点指针xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST "root");//设置根节点xmlDocSetRootElement(doc,root_node);//在根节点中直接创建节点xmlNewTextChild(root_node, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content");xmlNewTextChild(root_node, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content");xmlNewTextChild(root_node, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content");//创建一个节点,设置其内容和属性,然后加入根结点xmlNodePtr node = xmlNewNode(NULL,BAD_CAST "node2");xmlNodePtr content = xmlNewText(BAD_CAST "NODE CONTENT");xmlAddChild(root_node,node);xmlAddChild(node,content);xmlNewProp(node,BAD_CAST "attribute",BAD_CAST "yes");//创建一个儿子和孙子节点node = xmlNewNode(NULL, BAD_CAST "son");xmlAddChild(root_node,node);xmlNodePtr grandson = xmlNewNode(NULL, BAD_CAST "grandson");xmlAddChild(node,grandson);xmlAddChild(grandson, xmlNewText(BAD_CAST "This is a grandson node"));//存储xml文档int nRel = xmlSaveFile("CreateXml.xml",doc);if (nRel != -1){printf("一个xml文档被创建,写入%d个字节\n", nRel);}//释放文档内节点动态申请的内存xmlFreeDoc(doc);return 1;
}
编译 gcc CreateXmlFile.c -o CreateXmlFile -I/usr/local/include/libxml2 -lxml2
执行./CreateXmlFile,会生成一个XML文件CreatedXml.xml。打开后如下所示:
<?xml version="1.0"?><root><newNode1>newNode1 content</newNode1><newNode2>newNode2 content</newNode2><newNode3>newNode3 content</newNode3><node2 attribute="yes">NODE CONTENT</node2><son><grandson>This is a grandson node</grandson></son></root>
最好使用类似XMLSPY这样的工具打开,因为这些工具可以自动整理XML文件的栅格,否则很有可能是没有任何换行的一个XML文件,可读性较差。
28. 解析XML文档
(1)XML解析流程
解析一个XML文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点的属性。其流程如下:
① 用xmlReadFile函数读入一个文件,并返回一个文档指针doc。
② 用xmlDocGetRootElement函数得到根节点curNode。
③ 此时curNode->xmlChildrenNode就是根节点的首个儿子节点,该儿子节点的兄弟节点可用next指针进行轮询。
④ 轮询所有子节点,找到所需的节点,用xmlNodeGetContent取出其内容。
⑤ 用xmlHasProp查找含有某个属性的节点,属性列表指针xmlAttrPtr将指向该节点的属性列表。
⑥ 取出该节点的属性,用xmlGetProp取出其属性值。
⑦ xmlFreeDoc函数关闭文档指针,并清除本文档中所有节点动态申请的内存。
(2)XML解析举例
ParseXmlFile.c源代码如下:
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
int main(int argc, char* argv[])
{xmlDocPtr doc; //定义解析文件指针xmlNodePtr curNode; //定义结点指针xmlChar *szKey; //临时字符串变量char *szDocName;if (argc <= 1){printf("Usage: %s docname", argv[0]);return(0);}szDocName = argv[1];doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER);//解析文件//检查解析文档是否成功,如果不成功,libxml将报错并停止解析。//一个常见错误是不适当的编码,XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存if (NULL == doc){ fprintf(stderr,"Document not parsed successfully."); return -1;}//获取根节点curNode = xmlDocGetRootElement(doc);if (NULL == curNode){fprintf(stderr,"empty document");xmlFreeDoc(doc);return -1;}//确认根元素名字是否符合if (xmlStrcmp(curNode->name, BAD_CAST "root")){fprintf(stderr,"document of the wrong type, root node != root");xmlFreeDoc(doc);return -1;}curNode = curNode->xmlChildrenNode;xmlNodePtr propNodePtr = curNode;while(curNode != NULL){//取出节点中的内容if ((!xmlStrcmp(curNode->name, (const xmlChar *) "newNode1"))){szKey = xmlNodeGetContent(curNode);printf("newNode1: %s\n", szKey);xmlFree(szKey);}//查找带有属性attribute的节点if (xmlHasProp(curNode,BAD_CAST "attribute")){propNodePtr = curNode;}curNode = curNode->next;}//查找属性xmlAttrPtr attrPtr = propNodePtr->properties;while (attrPtr != NULL){if (!xmlStrcmp(attrPtr->name, BAD_CAST "attribute")){xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "attribute");printf("get attribute=%s\n", szAttr) ;xmlFree(szAttr);}attrPtr = attrPtr->next;}xmlFreeDoc(doc);return 0;
}
编译 gcc ParseXmlFile.c -o ParseXmlFile -I/usr/local/include/libxml2 -lxml2。
执行 ./ParseXmlFile CreateXml.xml,执行结果如下:
newNode1: newNode1 content
get attribute=yes
29. 修改XML文档
有了上面的基础,修改XML文档的内容就简单了。首先打开一个已经存在的XML文档,顺着根结点找到需要添加、删除、修改的地方,调用相应的XML函数对节点进行增、删、改操作。
需要注意的是,并没有xmlDelNode或者xmlRemoveNode函数,删除节点需使用以下一段代码:
if (!xmlStrcmp(curNode->name, BAD_CAST "newNode1")){xmlNodePtr tempNode;tempNode = curNode->next;xmlUnlinkNode(curNode);xmlFreeNode(curNode);curNode = tempNode;continue;}
此段代码完成将当前节点从文档中断链(unlink),这样此XML文档就不会再包含这个节点,该节点断链后需使用xmlFreeNode来释放该节点申请的动态内存空间。
30. 使用XPath查找XML文档
在libxml2中使用XPath非常简单,其流程如下:
① 定义一个XPath上下文指针xmlXPathContextPtr context,并且使用xmlXPathNewContext函数来初始化这个指针。
② 定义一个XPath对象指针xmlXPathObjectPtr result,并且使用xmlXPathEvalExpression函数来计算XPath表达式,得到查询结果,将结果存入对象指针中。
③ 使用result->nodesetval得到节点集合指针,其中包含了所有符合XPath查询结果的节点。
④ 使用xmlXPathFreeContext释放上下文指针。
⑤ 使用xmlXPathFreeObject释放XPath对象指针。
XPath操作代码示例如下:
xmlXPathObjectPtr getNodeSet(xmlDocPtr doc, const xmlChar *szXpath)
{xmlXPathContextPtr context; //XPath上下文指针xmlXPathObjectPtr result; //XPath对象指针,用来存储查询结果context = xmlXPathNewContext(doc); //创建一个XPath上下文指针if (context == NULL){ printf("context is NULL"n");return NULL;}result = xmlXPathEvalExpression(szXpath, context); //查询XPath表达式,得到一个查询结果xmlXPathFreeContext(context); //释放上下文指针if (result == NULL){printf("xmlXPathEvalExpression return NULL"n");return NULL;}if (xmlXPathNodeSetIsEmpty(result->nodesetval)) //检查查询结果是否为空{xmlXPathFreeObject(result);printf("nodeset is empty"n");return NULL;}return result;
}
30、 用iconv解决XML中字符集问题
libxml2中默认的内码是UTF-8,所有使用libxml2进行处理的xml文件,必须首先显式或者默认转换为UTF-8编码才能被处理。
要在XML中使用中文,就必须能够在UTF-8和GB2312之间进行转换。libxml2提供了默认的内码转换机制,并且在libxml2的Tutorial中有一个例子,事实证明这个例子并不很适合用来转换中文。
有些场合需要使用iconv来进行编码转换,libxml2本身也是使用iconv进行编码转换的。iconv是一个专门用来进行编码转换的库,基本上支持目前所有常用的编码,它是glibc库的一个部分。
本节其实和libxml没有太大关系,可以把它简单看作是一个编码转换方面的专题。下文提供了一个通用转码函数,并在此基础上实现了两个转码封装函数,即从UTF-8转换到GB2312的函数u2g,以及反向转换的函数g2u。其代码如下:
#include <iconv.h>
#include <string.h>
//代码转换,从一种编码转为另一种编码
int code_convert(char* from_charset, char* to_charset, char* inbuf, int inlen, char* outbuf, int outlen)
{iconv_t cd;char** pin = &inbuf; char** pout = &outbuf;cd = iconv_open(to_charset,from_charset); if(cd == 0)return -1;memset(outbuf,0,outlen); if(iconv(cd,(const char**)pin,(unsigned int *)&inlen,pout,(unsigned int*)&outlen) == -1)return -1; iconv_close(cd);return 0;
}
//UNICODE码转为GB2312码
//成功则返回一个动态分配的char*变量,需要在使用完毕后手动free,失败返回NULL
char* u2g(char *inbuf)
{int nOutLen = 2 * strlen(inbuf) - 1;char* szOut = (char*)malloc(nOutLen);if (-1 == code_convert("utf-8","gb2312",inbuf,strlen(inbuf),szOut,nOutLen)){free(szOut);szOut = NULL;}return szOut;
}
//GB2312码转为UNICODE码
//成功则返回一个动态分配的char*变量,需要在使用完毕后手动free,失败返回NULL
char* g2u(char *inbuf)
{int nOutLen = 2 * strlen(inbuf) - 1;char* szOut = (char*)malloc(nOutLen);if (-1 == code_convert("gb2312","utf-8",inbuf,strlen(inbuf),szOut,nOutLen)){free(szOut);szOut = NULL;}return szOut;
}
下面以UTF-8到GB2312转码流程说明上文中转码函数的使用,使用流程如下:
① 得到一个UTF-8的字符串szSrc。
② 定义一个char *的字符指针szDes,并不需要给它动态申请内存。
③ 调用szDes = u2g(szSrc),这样szDes就指向转换后GB2312编码的字符串。
④ 使用完这个字符串后使用free(szDes)来释放内存。
如果转码文件可以选择系统调用来进行文件转码。下文中f表示from,t表示to,其转码方法如下:
system(“iconv –f 源格式 –t 目标格式 源文件 >目标文件”)
system(“iconv –f GB18030 –t UTF-8 test_gb.txt > test_utf.txt”)
XML概述、语法及常用操作相关推荐
- JavaScript之基础-9 JavaScript String(内置对象、String概述、字符串常用操作、模式匹配)...
一.JavaScript 内置对象 内置对象 - 什么是内置对象? 内置对象就是ECMAScript标准中已经定义好的,由浏览器厂商已经实现的标准对象 - 内置对象中封装了专门的数据和操作数据常用的A ...
- weak_ptr概述,weak_ptr常用操作、尺寸
一.weak_ptr概述:weak_ptr辅助shared_ptr进行工作 weak"弱",反义词"强" 强值得就是shared_ptr,弱指的就是weak_p ...
- Spark SQL概述,DataFrames,创建DataFrames的案例,DataFrame常用操作(DSL风格语法),sql风格语法
一. Spark SQL 1. Spark SQL概述 1.1. 什么是Spark SQL Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作 ...
- 数学建模速成! 两小时零基础入门 MATLAB 教程(一)—— Matlab常用操作和基本语法
Matlab常用操作和基本语法 没有涉及到编程的内容, 就是介绍一些MATLAB软件的操作, 和简单的语法如注释输出之类的 目录 文章目录 Matlab常用操作和基本语法 1. help查看函数说明 ...
- MySQL常用操作之创建存储过程语法详解
MySQL常用操作之创建存储过程语法详解 前言 简介 语法 创建结构 变量结构 入参变量和出参变量 流程控制 判断(IF 语句) 判断(CASE 语句) 循环(LOOP 语句) 循环(WHILE 语句 ...
- Python基础语法(五)—常用模块和模块的安装和导入
Python基础语法(五)-常用模块的使用和模块的安装和导入,本文介绍的Python模块有:os.sys.time.datetime.random.pickle.json.hashlib.shutil ...
- phoenix的元数据一般存在哪里_Phoenix常用操作记录-阿里云开发者社区
Apache Phoenix 常用操作 基础知识 1****.****Phoenix 主要技术点 a.将SQL转化为HBase Scan,将结果封装为JDBC Result Set. b.表的元数据保 ...
- python序列类型-什么是序列,Python序列详解(包括序列类型和常用操作)
所谓序列,指的是一块可存放多个值的连续内存空间,这些值按一定顺序排列,可通过每个值所在位置的编号(称为索引)访问它们. 为了更形象的认识序列,可以将它看做是一家旅店,那么店中的每个房间就如同序列存储数 ...
- 编写XML作为配置文件的高级操作库
编写XML作为配置文件的高级操作库 yipsilon 原创 (参与分:293,专家分:180) 发表:2003-7-29 下午4:26 更新:2003-7-30 上午8:30 版本:1. ...
最新文章
- java对象的强引用,软引用,弱引用和虚引用
- 【Android 逆向】APK 文件处理脚本 ApkTool.py ( 脚本简介 | 用法 | 分析 APK 文件 )
- 一文搞懂负载均衡中的一致性哈希算法
- [html] html6即将到来,你最期待的是什么特性呢?
- 阿里云携领先SDN能力,亮相全球网络技术盛会ONS
- 有了解过Elasticsearch的性化搜索方案吗?
- java JDBC入门及案例演示
- 如何在 Mac 上使用“接力”回到上次离开的地方?
- 2010工作代码总结之三(repostioryItemGridLookUpEdit下拉框)
- ADS仿真设计AB类射频功率放大器
- ElementUI表格表头对角线的绘制
- 如何用python做比分网_使用python对历届世界杯进行数据分析
- C语言中char s[] 和 char *s的区别
- 今天开通个人博客,值得祝贺!
- Box2D例子——打砖块
- Rational Rose 2003下载与破解安装
- MySQL入门:数据库是什么 | SQL是什么 | MySQL是什么
- 彻底解决不要脸的360更改浏览器主页【转载】
- 新媒体研究杂志社新媒体研究编辑部新媒体研究杂志2022年第18期目录
- 利用USGS网站下载Landsat系列影像(个人总结的小技巧,适用新手小白)
热门文章
- 浅谈Attention机制的作用
- Gartner 2021年全球IaaS报告:AWS蛋糕被蚕食,中国云厂商稳步进击
- 利用鼠标实现画图功能 java
- Windows_一些小功能
- js异步与同步的区别
- 认知智能真的来了?且看道翰天琼认知智能三大技术体系-1!
- ViewBag(动态视图)、ViewData、ViewDataDictionary区分
- php隐藏指定id的div,CSS_纯css3显示隐藏一个div特效的具体实现,复制代码代码如下: !DOCTYPE H - phpStudy...
- IOS手机端页面在项目中遇到的一些问题及解决办法
- 加密托管风起:做区块链世界的银行