概述 |
如果您研究过 HTML 文档,您会熟悉使用标记来标注文档文本的基本概念。本章讨论 HTML 文档和 XML 文档之间的区别。它介绍了 XML 文档的基本规则,并讨论了用于描述它们的术语。
关于 XML 文档,有一点很重要:XML 规范需要解析器拒绝任何没有遵守基本规则的 XML 文档。大多数 HTML 解析器接受随意的标记,它们会猜测文档作者的意图。为了避免一般的 HTML 文档中松散结构所造成的混乱,XML 的创造者们决定从一开始就强制文档结构。
(如果您不熟悉解析器,那么顺便说明一下:解析器是尝试读取文档并解释其内容的一段代码。)
无效、有效以及格式良好的文档 |
有三种 XML 文档:
- 无效文档没有遵守 XML 规范定义的语法规则。如果开发人员已经在 DTD 或模式中定义了文档能够包含什么,而某个文档没有遵守那些规则,那么这个文档也是无效的。(请参阅定义文档内容以获得对 XML 文档 的 DTD 和模式的专门介绍。)
- 有效文档既遵守 XML 语法规则也遵守在其 DTD 或模式中定义的规则。
- 格式良好的文档遵守 XML 语法,但没有 DTD 或模式。
根元素 |
XML 文档必须包含在一个单一元素中。这个单一元素称为根元素,它包含文档中所有文本和所有其它元素。在下面的示例中,XML 文档包含在一个单一元素
<greeting>
中。请注意文档有一行注释在根元素之外;那是完全合乎规则的。 <?xml
version="1.0"?>
<!-- A well-formed document -->
<greeting> Hello, World! </greeting>
下面是一个不包含单一根元素的文档:
<?xml
version="1.0"?>
<!-- An invalid document -->
<greeting> Hello, World!</greeting>
<greeting> Hola, el Mundo!</greeting>
不管该文档可能包含什么信息,XML 解析器都会拒绝它。
元素不能重叠 |
XML 元素不能重叠。下面是一些不合乎规则的标记:
<!--NOT
legal XML markup -->
<p>
<b>I <i>really love
</b> XML.</i>
</p>
如果您在 <b>
元素中开始了 <i>
元素,则必须在 <b>
元素中结束 <i>
元素。如果您希望文本 XML
以斜体出现,那么您需要添加第二个 <i>
元素以更正标记:
<!--legal
XML markup -->
<p>
<b>I
<i>really love
</i>
</b>
<i>XML.</i>
</p>
XML 解析器将只接受这种标记;大多数 Web 浏览器中的 HTML 解析器对于两者都接受。
结束标记是必需的 |
不能省去任何结束标记。在下面第一个示例中,标记是不合乎规则的,因为没有结束段落(
</p>
)标记。尽管这在 HTML(以及某些情况下在 SGML)中可以接受,但 XML 解析器将拒绝它。 <!--NOT legal XML markup --> <p>Yada yada yada... <p>Yada yada yada...
<p>...
如果一个元素根本不包含标记,则称为空元素;HTML 换行(<br>
)和图像(<img>
)元素就是两个例子。在 XML 文档的空元素中,您可以把结束斜杠放在开始标记中。下面的两个换行元素和两个图像元素对于 XML 解析器来说是一回事:
<!--Two equivalent break elements -->
<br></br>
<br />
<!-- Two equivalent image elements -->
<img src="../img/c.gif"></img>
<img src="../img/c.gif" />
元素是区分大小写的
XML 元素是区分大小写的。在 HTML 中,<h1>
和 <H1>
是相同的;在
XML 中,它们是不同的。如果您试图用 </H1>
标记结束 <h1>
元素,将会出错。在下面的示例中,顶部的标题是不合乎规则的,而底部的则是正确的。 <!--NOT legal XML markup -->
<h1>Elements are case sensitive</H1>
<!--legal XML markup -->
<h1>Elements are case sensitive</h1>
属性必须有用引号括起的值
XML 文档中的属性有两个规则:
- 属性必须有值
- 那些值必须用引号括起。
比较下面的两个示例。顶部的标记在 HTML 中是合乎规则的,但在 XML 中则不是。为了在 XML 中取得相同结果,您必须给属性赋值,而且必须把值括在引号中。
<!--NOT legal XML markup -->
<ol compact>
<!-- legal XML markup -->
<ol compact="yes">
您可以使用单引号,也可以使用双引号,但要始终保持一致。
如果属性值包含单引号或双引号,则您可以使用另一种引号来括起该值(如 name="Doug's
car"
),或使用实体 "
代表双引号,使用 '
代表单引号。实体是一个符号(如 "
),XML
解析器会用其它文本代替该符号(如 "
)。
XML 声明
大多数 XML 文档以 XML 声明作为开始,它向解析器提供了关于文档的基本信息。建议使用 XML 声明,但它不是必需的。如果有的话,那么它一定是文档的第一样东西。
声明最多可以包含三个名称-值对(许多人称它们为属性,尽管在技术上它们并不是)。version
是使用的
XML 版本;目前该值必须是 1.0
。encoding
是该文档所使用的字符集。该声明中引用的 ISO-8859-1
字符集包括大多数西欧语言用到的所有字符。如没有指定 encoding
,XML
解析器会假定字符在 UTF-8
字符集中,这是一个几乎支持世界上所有语言的字符和象形文字的
Unicode 标准。
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
最后,standalone
(可以是 yes
或 no
)定义了是否可以在不读取任何其它文件的情况下处理该文档。例如,如果
XML 文档没有引用任何其它文件,则您可以指定 standalone="yes"
。如果
XML 文档引用其它描述该文档可以包含什么的文件(马上会详细介绍这些文件),则您可以指定 standalone="no"
。因为 standalone="no"
是缺省的,所以您很少会在
XML 声明中看到 standalone
。
<!--NOT legal XML markup -->
<h1>Elements are case sensitive</H1>
<!--legal XML markup -->
<h1>Elements are case sensitive</h1>
属性必须有用引号括起的值
XML 文档中的属性有两个规则:
- 属性必须有值
- 那些值必须用引号括起。
比较下面的两个示例。顶部的标记在 HTML 中是合乎规则的,但在 XML 中则不是。为了在 XML 中取得相同结果,您必须给属性赋值,而且必须把值括在引号中。
<!--NOT legal XML markup -->
<ol compact>
<!-- legal XML markup -->
<ol compact="yes">
您可以使用单引号,也可以使用双引号,但要始终保持一致。
如果属性值包含单引号或双引号,则您可以使用另一种引号来括起该值(如 name="Doug's
car"
),或使用实体 "
代表双引号,使用 '
代表单引号。实体是一个符号(如 "
),XML
解析器会用其它文本代替该符号(如 "
)。
XML 声明
大多数 XML 文档以 XML 声明作为开始,它向解析器提供了关于文档的基本信息。建议使用 XML 声明,但它不是必需的。如果有的话,那么它一定是文档的第一样东西。
声明最多可以包含三个名称-值对(许多人称它们为属性,尽管在技术上它们并不是)。version
是使用的
XML 版本;目前该值必须是 1.0
。encoding
是该文档所使用的字符集。该声明中引用的 ISO-8859-1
字符集包括大多数西欧语言用到的所有字符。如没有指定 encoding
,XML
解析器会假定字符在 UTF-8
字符集中,这是一个几乎支持世界上所有语言的字符和象形文字的
Unicode 标准。
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
最后,standalone
(可以是 yes
或 no
)定义了是否可以在不读取任何其它文件的情况下处理该文档。例如,如果
XML 文档没有引用任何其它文件,则您可以指定 standalone="yes"
。如果
XML 文档引用其它描述该文档可以包含什么的文件(马上会详细介绍这些文件),则您可以指定 standalone="no"
。因为 standalone="no"
是缺省的,所以您很少会在
XML 声明中看到 standalone
。
XML 文档中的其它项 |
您或许会在一个 XML 文档中发现其它几项:
- 注释:注释可以出现在文档的任何位置;它们甚至可以出现在根元素的前面或后面。注释以
<!--
开始,以-->
结束。注释不能在结束部分以外包含双连字符(--
);除此之外,注释可以包含任何内容。最重要的是,注释内的任何标记都被忽略;如果您希望除去 XML 文档的一块较大部分,只需用注释括住那个部分即可。(要恢复这个注释掉的部分,只需除去注释标记即可。)下面是包含注释的标记:
<!--Here's a PI for Cocoon: -->
<?cocoon-process type="sql"?>
- 处理指令:处理指令是为使用一段特殊代码而设计的标记。在上面的示例中,有一个用于 Cocoon 的处理指令(有时称为 PI),Cocoon 是来自 Apache 软件基金会(Apache Software Foundation)的 XML 处理框架。当 Cocoon 处理 XML 文档时,它会寻找以
cocoon-process
开头的处理指令,然后相应地处理 XML 文档。在该示例中,type="sql"
属性告诉 Cocoon:XML 文档包含一个 SQL 语句。
<!--Here's an entity: -->
<!ENTITY dw "developerWorks">
- 实体:上面的示例为文档定义了一个实体。无论 XML 处理器在何处找到字符串
&dw;
,它都会用字符串developerWorks
代替该实体。XML 规范还定义了五个您可以用来替代不同的特殊字符的实体。这些实体是:<
代表小于符号>
代表大于符号"
代表一个双引号'
代表一个单引号(或撇号)&
代表一个“与”符号。
名称空间 |
XML 的能力来自它的灵活性,即您和我以及数百万其他人可以定义我们自己的标记来描述我们的数据。记得表示个人姓名和地址的样本 XML 文档吗?那个文档包括表示个人尊称的 <title>
元素,这是对元素名称非常合理的选择。如果您经营一家网上书店,您或许会创建一个表示书名的 <title>
元素。如果您经营一家网上抵押放款公司,您或许会创建表示一份财产名称的 <title>
元素。所有这些都是合理的选择,但它们都用相同的名称创建元素。如何分辨某个特定的 <title>
元素指的是人、书籍还是一份财产呢?可以使用名称空间。
要使用名称空间,您要定义一个名称空间前缀,然后将它映射至一个特殊字符串。下面介绍如何定义我们这三个 <title>
元素的名称空间前缀:
<?xml version="1.0"?>
<customer_summary
xmlns:addr="http://www.xyz.com/addresses/"
xmlns:books="http://www.zyx.com/books/"
xmlns:mortgage="http://www.yyz.com/title/"
>
...
<addr:name>
<title>Mrs.</title> ...
</addr:name>
...
...
<books:title>Lord of the Rings</books:title>
...
...
<mortgage:title>NC2948-388-1983</mortgage:title>
...
在该示例中,三个名称空间前缀是 addr
、books
和 mortgage
。请注意,为特定元素定义名称空间意味着该元素的所有子元素都属于同一名称空间。第一个 <title>
元素属于 addr
名称空间,因为其父元素 <addr:Name>
属于该名称空间。
最后要指出的是:名称空间定义中的字符串仅仅是字符串。对,这些字符串看似 URL,其实不是。您可以定义 xmlns:addr="mike"
,那也是有效的。名称空间唯一的重要性在于其唯一性;这就是为什么大多数名称空间定义看起来象
URL 的原因。XML 解析器不会到 http://www.zyx.com/books/
去搜索
DTD 或模式,它只是把那个文本作为字符串使用。这有些令人困惑,但名称空间就是这样工作的。