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
&copyright;

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概述、语法及常用操作相关推荐

  1. JavaScript之基础-9 JavaScript String(内置对象、String概述、字符串常用操作、模式匹配)...

    一.JavaScript 内置对象 内置对象 - 什么是内置对象? 内置对象就是ECMAScript标准中已经定义好的,由浏览器厂商已经实现的标准对象 - 内置对象中封装了专门的数据和操作数据常用的A ...

  2. weak_ptr概述,weak_ptr常用操作、尺寸

    一.weak_ptr概述:weak_ptr辅助shared_ptr进行工作 weak"弱",反义词"强" 强值得就是shared_ptr,弱指的就是weak_p ...

  3. Spark SQL概述,DataFrames,创建DataFrames的案例,DataFrame常用操作(DSL风格语法),sql风格语法

    一. Spark SQL 1. Spark SQL概述 1.1. 什么是Spark SQL Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作 ...

  4. 数学建模速成! 两小时零基础入门 MATLAB 教程(一)—— Matlab常用操作和基本语法

    Matlab常用操作和基本语法 没有涉及到编程的内容, 就是介绍一些MATLAB软件的操作, 和简单的语法如注释输出之类的 目录 文章目录 Matlab常用操作和基本语法 1. help查看函数说明 ...

  5. MySQL常用操作之创建存储过程语法详解

    MySQL常用操作之创建存储过程语法详解 前言 简介 语法 创建结构 变量结构 入参变量和出参变量 流程控制 判断(IF 语句) 判断(CASE 语句) 循环(LOOP 语句) 循环(WHILE 语句 ...

  6. Python基础语法(五)—常用模块和模块的安装和导入

    Python基础语法(五)-常用模块的使用和模块的安装和导入,本文介绍的Python模块有:os.sys.time.datetime.random.pickle.json.hashlib.shutil ...

  7. phoenix的元数据一般存在哪里_Phoenix常用操作记录-阿里云开发者社区

    Apache Phoenix 常用操作 基础知识 1****.****Phoenix 主要技术点 a.将SQL转化为HBase Scan,将结果封装为JDBC Result Set. b.表的元数据保 ...

  8. python序列类型-什么是序列,Python序列详解(包括序列类型和常用操作)

    所谓序列,指的是一块可存放多个值的连续内存空间,这些值按一定顺序排列,可通过每个值所在位置的编号(称为索引)访问它们. 为了更形象的认识序列,可以将它看做是一家旅店,那么店中的每个房间就如同序列存储数 ...

  9. 编写XML作为配置文件的高级操作库

    编写XML作为配置文件的高级操作库 yipsilon 原创  (参与分:293,专家分:180)   发表:2003-7-29 下午4:26   更新:2003-7-30 上午8:30   版本:1. ...

最新文章

  1. java对象的强引用,软引用,弱引用和虚引用
  2. 【Android 逆向】APK 文件处理脚本 ApkTool.py ( 脚本简介 | 用法 | 分析 APK 文件 )
  3. 一文搞懂负载均衡中的一致性哈希算法
  4. [html] html6即将到来,你最期待的是什么特性呢?
  5. 阿里云携领先SDN能力,亮相全球网络技术盛会ONS
  6. 有了解过Elasticsearch的性化搜索方案吗?
  7. java JDBC入门及案例演示
  8. 如何在 Mac 上使用“接力”回到上次离开的地方?
  9. 2010工作代码总结之三(repostioryItemGridLookUpEdit下拉框)
  10. ADS仿真设计AB类射频功率放大器
  11. ElementUI表格表头对角线的绘制
  12. 如何用python做比分网_使用python对历届世界杯进行数据分析
  13. C语言中char s[] 和 char *s的区别
  14. 今天开通个人博客,值得祝贺!
  15. Box2D例子——打砖块
  16. Rational Rose 2003下载与破解安装
  17. MySQL入门:数据库是什么 | SQL是什么 | MySQL是什么
  18. 彻底解决不要脸的360更改浏览器主页【转载】
  19. 新媒体研究杂志社新媒体研究编辑部新媒体研究杂志2022年第18期目录
  20. 利用USGS网站下载Landsat系列影像(个人总结的小技巧,适用新手小白)

热门文章

  1. 浅谈Attention机制的作用
  2. Gartner 2021年全球IaaS报告:AWS蛋糕被蚕食,中国云厂商稳步进击
  3. 利用鼠标实现画图功能 java
  4. Windows_一些小功能
  5. js异步与同步的区别
  6. 认知智能真的来了?且看道翰天琼认知智能三大技术体系-1!
  7. ViewBag(动态视图)、ViewData、ViewDataDictionary区分
  8. php隐藏指定id的div,CSS_纯css3显示隐藏一个div特效的具体实现,复制代码代码如下: !DOCTYPE H - phpStudy...
  9. IOS手机端页面在项目中遇到的一些问题及解决办法
  10. 加密托管风起:做区块链世界的银行