XML(Extensible Markup Lanaguage),可扩展标记语言,是标准通用标记语言(Standard Generalized Markup Language, SGML)的一个子集,SGML功能强大,是可以定义标记语言的元语言。将强大的SGML的通用性和HTML的易用性结合起来便诞生了适合在Web中应用的XML语言。
1、起源
1998年2月W3C(万维网联盟)发布了XML1.0标准,其目的是为了在Web上能以现有的超文本标记语言(HTML)的使用方式提供、接收和处理通用的SGML。XML是SGML的一个简化子集,它以一种开放的自我描述的方式定义了数据结构。在描述数据内容的同时能突出对结构的描述,从而体现出数据与数据之间的关系。
2、SGML、HTML和XML
SGML是在web发明以前就早已存在的使用标记来描述文档资料的通用语言,它是一种定义标记语言的元语言。HTML和XML都是从SGML发展而来的标记语言。因此,它们有一些共同的特点,如相似的语法和标记的使用。不过,HTML是在SGML定义下的一个描述性语言,只是SGML的一个应用,其DTD作为标准被固定下来,而XML是SGML的一个简化版本,是SGML的一个子集,严格意义上来说,XML仍是SGML。
如下面的例子:
HTML: <html> <head> <title>这是一个欢迎的例子</title> <head> <body> 你好,你好! <body> </html> XML: <?xml version=”1.0” encoding=”gb2312”?> <欢迎词> <标题>这是一个欢迎的例子</标题> <内容>你好,你好!</内容> </欢迎词>
可以看出HTML的标记都是固定的,而XML的标记都是用户自定义的。因此HTML和XML处在标记语言中的不同层次,XML是创建标记语言的元语言。
HTML文档将数据、页面排版以及页面的表现形式混合在一起,如果要增加新的数据就要调整数据的排版与显示方式。当从其他地方获得数据,一旦放入html文档中,整个数据就会被打乱,数据和html标记混合在一起,数据本身变得无法辨析。
XML无法描述页面的排版和表现形式,只是用来描述数据和数据的结构。XML将数据和数据的显示分开,我们可以为这些数据设计不同的显示和表现形式(可以对其应用不同的样式表),而数据本身无需做任何修改。XML使数据能够独立于应用系统,数据可以重用,一份数据可以用于不同的场合。有时XML文档被看做文档的数据刻画和数据的文档化。
HTML文档格式非常松散,导致html文档解析的复杂性,也造成了浏览器兼容的问题。XML对文档的格式制定了严格的标准,凡是符合这一标准的xml文档就是格式良好的xml文档(Well-Formed XML Documents)。
3、XML组成
XML文档在逻辑上主要由以下五个部分组成:
XML声明
文档类型声明
元素
注释
处理指令
XML标记(markup)包括开始标签(tag)、结束标签、空元素标签、实体引用、字符引用、注释、CDATA段定界符、文档类型声明、处理指令、XML声明、文本声明以及任何在文档实体顶层的空白(即在文档元素之外,且不在任何其它的标记内部)。其他所有非标记的文本组成文档的字符数据。
3.1 XML声明
XML文档总是以一个XML声明开始,其中指明所用的XML版本、文档的编码、文档的独立性信息。格式如下:
<?xml 版本信息 [编码信息] [文档独立性信息]?>
XML声明必须位于xml文档的第一行,之前不能有任何字符。
3.1.1版本声明
<?xml version=”1.0”?>
3.1.2 文档编码声明
在XML声明中还可以加上文档编码信息,默认是UTF-8,如果要使用中文,我们可以在声明中加上encoding=”gb2312”(gb2312是中文字符集),如下所示:
<?xml version=1.0 encoding=”gb2312”>
3.1.3 独立文档声明
如果我们的文档不依赖于外部文档,在XML声明中,我们可以通过standalone=”yes”来声明这个文档是独立的文档,如果文档依赖于外部文档,可以通过standalone=”no”来声明,完整的XML声明如下所示:
<?xml version=”1.0” encoding=”gb2312” standalone=”yes”>
3.2 文档类型声明
DTD(Document Type Definition),文档类型定义。
XML从SGML继承了用于定义语法规则的DTD机制,但DTD本身并不要求遵循XML规则,几乎所有的XML应用都是使用DTD来定义的,HTML就有一个标准的DTD文件,所以其组织结构和所有的标签都是固定的。DTD文件本事也是一个文本文件,通常用“.dtd”作为其扩展名。
通过文档类型声明,指出XML文档所用的DTD,文档类型声明有两种形式:一种是声明DTD在一个外部的文件中,如下:
<!DOCTYPE greeting SYSTEM “hello.dtd”>
greeting 指明xml文档根元素的名称,SYSTEM指明是私有的dtd文件一种是直接在XML文档中给出DTD,如下:
<?xml version=”1.0” encoding=”gb2312” standalone=”yes”?> <!DOCTYPE greeting [ <!ELEMENT greeting (#PCDATA)> ]>
3.3 元素
3.3.1 元素组成
在xml中,元素由开始标签、元素内容和结束标签构成,对于空元素,由空元素标签构成。每一个元素有一个用名字标识的类型,同时它可以有一个属性说明集,每一个属性说明有一个名字和一个值。
3.3.2 元素命名
在给元素命名的时候要注意,以xml或其他任何匹配((‘X’|’x’)(‘M’|’m’)(‘L’|’l’))的字符串开头的名字,被保留用于XML规范的当前版本或后续版本的标准化。此外,在给元素命名的时候,还要遵守以下规范:
名称只能以字母、下划线(_)或者冒号(:)开头;
名称中可以包含字母、数字、下划线以及其它在XML标准中允许的字符;
名称中不能包含空格;
名称中尽可能不要使用冒号(:),因为冒号在名称空间中被用于分割名称空间的前缀和本地部分。
3.3.3 元素的四种形式
(1) 空元素 <student/> (2) 带有属性的空元素 <student name=”张三” age=”18”/> (3) 带有内容的元素 <student> 这是一个学生的信息 <name>张三</name> <age>18</age> </student> (4) 带有内容和属性的元素 <student name=”张三”> <age>18</age> </student>
3.3.4元素和标签
元素和标签具有不同的含义。元素是指开始标签、结束标签以及两者之间的一切内容,包括属性、文本、注释以及子元素。标签是一对尖括号(< >)和两者之间的内容,包括元素名和所有属性。例如:<font color=”blue”>是一个标签,</font>也是一个标签;而<font color=”blue”>Hello World</font>则是一个元素。
3.3.5 元素的内容
4.3.5.1 元素内容的组成
元素的内容可以包含子元素、字符数据、字符引用和实体引用、CDATA段。
子元素本身也是元素,被嵌套在上层元素之内,子元素是相对于父元素而言的,如果子元素还嵌套了其他元素,那么它同时也是父元素。
在一个元素的内容中,字符数据可以是不包括任何标记的起始定界符和CDATA段的结束定界符的任意字符串,也就是说在元素的内容中,字符数据不能有和号(&)和小于号(<),也不能有字符串“]]>”。在CDATA段中,字符数据可以是不包括CDATA段的结束定界符的任意字符串。在字符数据中,不能有和号(&)和小于号(<),因为未经处理的小于号(<)与和号(&)在XML文本中往往被解释为标记的起始定界符(存在例外的情况,见CDATA段)。
4.3.5.2 预定义实体引用
在XML中,提供了五个预定义的实体引用,分别引用XML文档中的5个特殊字符:小于号(<)、大于号(>)、双引号(“)、单引号(‘)、和号(&)。这5个特殊字符也可以通过字符引用的方式去引用。
字符引用和预定义实体引用都是以一个和号(&)开始并以一个分号(;)结束,如果用的是字符引用,需要在和号(&)之后加上一个井号(#),之后是所需字符的十进制代码或十六进制代码(ISO/IEC 10646字符集中字符编码),如果用的是预定义实体引用,在和号(&)之后写上字符的助记符。
只要在ISO/IEC 10646字符集中的字符都可以通过其字符编码来引用,方式同上。
4.3.5.2 CDATA段
CDATA段中包含的都是纯字符数据,在字符数据可以出现的任何地方都可以使用CDATA段。CDATA段主要用于需要将整个文本解释为字符数据而不是标记的情况下。CDATA段中的内容不被XML处理器分析,所以可以在其中包含任意的字符。例如,在XML文档中,需要包含java代码,而java代码中可能存在着小于号、大于号、单引号、双引号、和号这些特殊字符,这个时候,CDATA段就派上用场了。
CDATA段以字符串”<!CDATA[”开始,以字符串”]]>”结束。
3.4 注释
在XML文档中,注释可以出现在文档中其它标记之外的任何位置,另外,它们还可以在文档类型声明中语法(grammar)允许的地方出现。XML的注释和HTML的注释类似,都是以<!—开始,以-->结束。位于<!—和-->之间的数据将被XML处理器忽略。如<!—This is a comment-->。注释用于对文档中的内容起一个说明作用。使用注释时,要注意一下五点:
注释部分不能出现在XML声明之前,XML声明必须是文档最前面的部分。下面的情况是不允许的:
注释不能出现在标记中。
注释可以包围和隐藏标记,但是要注意的是,在注释掉标记之后,要保证剩余的文本仍然是一个结构完整的XML文档,如:
字符串”--”(双连字符)不能再注释中出现。下面的例子是非法的: <!--This is a great example--Hello, World--> 在XML中,不允许注释以--->结尾。下面的例子是非法的: <!--This is a great example--->
3.5 处理指令
处理指令(Processing Instructions,简称PIs)允许文档中包含由应用程序来处理的指令。在XML文档中,有可能会包含一些非XML格式的数据,这些数据XML处理器无法处理,我们就可以通过处理指令来通知其它应用程序来处理这些数据。
处理指令(PI)的语法和XML声明类似,以<?开始,以?>结束。一个常见的使用样式表单的处理指令如下所示:
<?xml-stylesheet href=”hello.css” type=”text/css”?>
在开始标记<?后的第一个字符串”xml-stylesheet”叫做处理指令的目标,它必须标识要用到的应用程序,要注意的是对于其它的非W3C定义的处理指令不能以字符串”XML”和”xml”开头,其余的部分是传递给应用程序的字符数据。应用程序从处理指令中取得目标和数据,执行要求的动作。
处理指令的目标可以是要使用的程序的名字,或者是一个类似于xml-stylesheet这样的很多程序可以识别的通用标识符。不同的应用程序支持不同的处理指令,对于不认识的处理指令,大多数应用程序采取忽略的方式进行处理。Xml-stylesheet处理指令总是放在XML声明之后,第一个元素之前。其它的处理指令可以放在除标记的内部和XML声明之前的任何位置。
4、DTD(Document Type Definition)文档类型定义
DTD(Document Type Definition),文档类型定义。在XML标准中,描述了如何创建DTD,以及如何将它与根据它的规则所编写的XML文档相关联,并且还定义了XML处理器应该如何对DTD进行处理。有了DTD就可以检测XML文档的结构是否正确。DTD为XML文档的编写者和处理者提供了共同遵循的原则,使得与文档相关的各种工作有了统一的标准。
4.1 在XML文档中引入DTD
通过在XML文档中包含文档类型声明,来建立当前文档和DTD的关联,当进行有效性验证的XML处理器读到该指令时,它获取DTD,并根据其中定义的规则对文档进行检验,文档类型声明必须位于XML声明之后,且在根元素(文档元素)之前。不过,在XML声明和文档类型声明之间可以插入注释和处理指令。
我们可以直接在XML文档中定义DTD,也可以通过URI引用外部的DTD文件,或者同时采用这两种方式。
4.1.1 内部DTD
<?xml version=”1.0” encoding=’gb2312’ standalone=”yes”> <!DOCTYPE greeting[ <!ELEMENT greeting(#PCDATA)> ]>
文档类型声明由<!开始,后面紧跟一个关键字DOCTYPE,然后是文档根元素的名称,接下来是标记声明块,标记声明块是放在左中括号( [ )和右中括号( [ )之间的,由一个或多个标记声明构成,最后由>结束。
在DTD中,所有的关键字都是大写的。不过,在DTD中定义的元素和属性的大小写是可以任意指定的,但是要注意,因为XML文档时大小写相关的,所以一旦给一个元素命名,那么在整个文档中要使用相同的大小写,例如:greeting和Greeting是两个不同的元素名。
在XML文档中定义DTD,比较直观,修改也比较方便,而且不用担心XML处理器找不到DTD,但是他也有一些缺点:
在文档中定义DTD会导致文档本身的长度增加,在传输数据时,即使不需要验证文档的有效性,这些声明也会随着文档一起传输。
如果多个XML文档要公用一个DTD,我们就需要在每一个文档中加入DTD,这是相当繁琐的。
4.1.2 外部DTD
在文档类型声明时,用关键字SYSTEM或PUBLIC来指出外部DTD文件的位置。使用SYSTEM关键字的声明语法如下:
<!DOCTYPE 根元素的名字 SYSTEM “外部DTD文件的URI”>
SYSTEM关键字表示文档使用的是私有的DTD文件,“外部DTD文件的URI”可以是相对URI或者绝对URI,相对URI是相对于文档类型声明所在文档的位置。“外部DTD文件的URI”这部分也被称为系统标识符(system identifier),下面是一个使用外部DTD文件的例子:
<!DOCTYPE greeting SYSTEM “hello.dtd”>
如果位于不同位置的多个XML文档要使用同一个DTD,我们可以使用绝对URI来指明DTD文件的地址,假定hello.dtd位于http://www.lfqy.org/xml/dtds/hello.dtd,可以在文档类型声明中使用此URI:
<!DCOTYPE greeting SYSTEM “http://www.lfqy.org/xml/dtds/hello.dtd”>
如果引用DTD的XML文档与DTD文件在同一个web服务器上,我们也可以使用相对URL:
<!DCOTYPE greeting SYSTEM “/xml/dtds/hello.dtd”> <!DCOTYPE greeting SYSTEM “/dtds/hello.dtd”> <!DCOTYPE greeting SYSTEM “../hello.dtd”>
上面的三种形式都是允许的。
使用PUBLIC关键字的声明语法如下:
<?DOCTYE 根元素的名字 PUBLIC “DTD的名称” “外部DTD文件的URI”>
PUBLIC关键字用于声明公共的DTD,并且这个DTD还有一个名称,“DTD的名称”也称为公共标识符(public identifier)。这个DTD可以存放在某个公共的地方,XML处理器程序会根据名称按照某种方式去检索DTD,如果XML处理器不能根据名称检索到DTD,就会使用“外部DTD文件的URI”(系统标识符)来查找该DTD。
DTD名称与XML名称略有不同,它们只能包含ASCII字母和数字字符、空格、回车符、换行符和一些标点符号:- ‘ ( ) + . / : = ? ; ! # @ $ _ %。公共DTD的名称要遵守一些约定,如果一项DTD是ISO标准,它的名称要以字符串”ISO”开始,如果是一个非ISO的标准组织批准的DTD,它的名字以加号( + )开始,如果不是标准组织批准的DTD,它的名称以连字符( - )开始,这些开始字符或字符串后接双斜杠( // )和DTD所有者的名字,之后是另一个双斜杠和DTD描述的文档类型,接着又是一个双斜杠后接ISO 639语言标识符,如EN表示,ZH表示中文,在http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt处列有完整的ISO639标识符。
例如,我们定义的人力资源DTD可以采用下面的命名:
-//lfqy//DTD HR1.0//ZH
连字符( - )表示这个DTD不是由任何标准组织批准的,为lfqy所有,描述的是人力资源管理。用中文编写。完整的文档类型声明如下:
<!DOCTYPE HR PUBLIC “-//lfqy//DTD HR1.0//ZH” “http://www.lfqy.org/xml/dtds/hr.dtd”>
HTML网页的文档类型声明,如下:
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
W3C公布的在Web文档中使用的有效的文档类型声明列表可以在http://www.w3.org/QA/2002/04/valid-dtd-list.html上找到。
注意:
文档类型声明与文档类型定义不是一个概念,DTD是文档类型定义(Document Type Definition)的英文缩写。<!DOCTYPE greeting SYSTEM “hello.dtd”>是文档类型声明,<!ELEMENT greeting (#PCDATA)>这种语法是文档类型定义。文档类型声明可以包含(内部DTD子集)或引用(外部DTD子集)一个文档类型定义,但文档类型定义从不包含文档类型声明。
在前面我们提到,如果我们的文档不依赖于外部文档,在XML声明中,可以通过standalone=”yes”来声明这个文档是独立的文档。如果文档依赖于外部文档,可以通过standalone=”no”来声明。当我们使用外部DTD文件时,就需要将属性standalone值设置为”no”。
在实际应用中,很少使用standalone属性,它的主要用途是作为XML处理器和其他应用程序的标识,表示是否需要获取外部内容。如果文档依赖于外部文档,即使我们不适用standalone属性,XML处理器也能够很好地进行处理。