解释 XML 文档是如何组成的最好的方式就是呈现它。下面的例子展示了一个可能用来描述作者的 XML 文档:

<?xml version="1.0" emcoding="us-ascii"?>
<authors>
    <person id="lear">
        <name>Edward Lear</name>
        <nationality>British</nationality>
    </person>
    <person id="asimov">
        <name>Isaas Asimov</name>
        <nationality>American</nationality>
    </person>
    <person id="mysteryperson"/>
</authors>

文档的第一行被称作 XML 声明,用于告诉处理应用我们使用的是哪个版本的 XML(版本标志是强制的)以及这个文档使用的是哪种字符编码。在前面的例子中,文档使用的是 ASCII 编码(关于字符编码的重要性在本章后面讨论)。如果遗漏了 XML 声明,处理程序会对我们的文档作出某些假设。特别是,它期望我们使用 UTF-8 编码——Unicode 字符集编码。然而,最好是尽可能使用 XML 声明,这样既可以避免混淆字符编码,也可以告诉处理器我们使用的是哪个版本的 XML。

例子中的第二行以一个元素开始,被命名为 authors。这个元素的内容包括 <authors> 的右尖括号 ></authors> 的左尖括 < 之间的所有内容。实际的语法结构 <authors></authors> 通常分别被称为元素的起始标签结束标签。不要将标签和元素混淆!注意,元素可以包含其他元素,以及文本。XML 文档必须包含一个根元素,它包含文档中的所有其他内容。根元素的名称定义 XML 文档的类型。

同时包含文本和其他元素的元素被分类为混合内容。SVG 的 <text> 元素就是这样的元素。它可以包含文本和 <tspan> 元素。

这个简单的 authors 文档使用名为 <person> 的元素描述作者本身。每个 person 元素都有一个名为 id 的属性。和元素不同,属性只能包含文本型内容。它们的值必须使用引号包裹。单引号(')和双引号(")都可以使用,只要我们使用相同引号即可。

XML 文档中,属性经常用于元数据(即关于数据的数据)——描述元素内容的属性。这种情况在我们的例子中就是,id 包含一个要描述的 person 的唯一标识符。

就 XML 而言,属性出现在元素起始标签中的顺序是不重要的。例如,这里有两个元素,就 XML 1.0 处理应用程序而言,它们所包含的信息是相同的:

<animal name="dog" legs="4"/>
<animal legs="4" name="dog"/>

而另一方面,通过 XML 处理器阅读如下两行代码提交给应用程序的信息将会是两个不同的 animal 元素,因为元素的顺序是很重要的:

<animal><name>dog</name><legs>4</legs></animal>
<animal><legs>4</legs><name>dog</name></animal>

XML 处理一组属性就像把一堆东西装进包里——并没有隐含的顺序问题,而处理元素时就像列表上的项目,是存在顺序问题的。

XML 开发新手经常会问何时使用属性表示信息最好,何时使用元素最好。正如从 authors 例子中可以看到的,如果顺序很重要,那么使用元素是一个不错的选择。总之,并没有一成不变的“最佳实践”告诉我们是选择属性还是元素。

我们的文档中最后描述的 author 并没有什么可用信息。我们只知道这个人的 ID 是 mysteryperson。文档使用了 XML 快捷语法来表示空元素。和下面的形式是等价的:

<person id="mysteryperson"></person>

XML 1.0 对命名元素和属性有一定的规则。特别是:

  • 命名区分大小写,比如 <person/><Person/> 是不一样的;

  • xml 开始的命名(包括任意变换的大小写形式)是为 XML 1.0 和它的附属规范预留的;

  • 命名必须以字母或者下划线开头,不能是数字,可以包含任意字母、数字、下划线或者句点。2

2实际上,一个名称还可以包含冒号,但冒号被用来分隔命名空间前缀,并且它也不能随意使用。更多信息请查看 Tim Bray 的“XML 命名空间示例”:http://www.xml.com/pub/a/1999/01/namespaces.html

关于命名更准确的描述可以在 XML 1.0 规范的 2.3 节(http://www.w3.org/TR/REC-xml/#sec-common-syn)找到。XML 1.1 的命名规则略有不同,主要是关于 Unicode 字符。SVG 使用的是 XML 1.0 规则。

遵从 XML 语法规则的 XML 文档被认为是合法形式。从本质上来看,结构的完整性意味着元素必须正确匹配,所有元素都应该闭合。关于结构完整性的正式定义可以在 XML 1.0 规范的 2.1 节(http://www.w3.org/TR/REC-xml/#sec-well-formed)找到。表 A-1 展示了一些不正确的 XML 文档。

表A-1:不正确的XML文档示例

文档

错误原因

<foo>
<bar>
</foo>
</bar>

元素嵌套不正确,因为 foo 闭合在它的子元素 bar 里面了

<foo>
<bar>
</foo>

bar 元素在它的父元素 foo 闭合之前没有闭合

<foo baz>
</foo>

baz 属性没有值。虽然在 HTML 中可以(比如 <table border>),但是在 XML 中不行

<foo baz=23>
</foo>

baz 属性的值 23 没有使用引号包裹。和 HTML 不同,XML 中所有的属性值必须用引号包裹

和 HTML 一样,XML 文档中也可以包含注释。XML 注释被设计为面向人类可读。对于 HTML 而言,开发人员偶尔会使用特定的注释来添加功能。例如,大多数 Web 服务器都支持的“服务端包含”(Server Side Include,简称 SSI)功能就是以嵌入 HTML 注释的方式使用的。XML 提供了其他可供应用程序处理的指令 3,因此注释不应该用于除了说明性文字之外的任何其他目的。

3关于处理指令(PIs)的讨论在本书范围之外。更多关于 PIs 的信息,请参考 XML 1.0 规范的 2.6 节,在 http://www.w3.org/TR/REC-xml#sec-pi

注释的开头用 <!-- 表示,以 --> 结束。任何除 -- 以外的字符序列,都可以出现在注释中。

XML 文档中的注释往往更多的是用于人类理解而不是机器理解。SVG 中的 <desc><title> 元素可以避免大部分注释需求。

编写 SVG 文档时 XML 的另一个特性偶尔会大有用处,就是它的字符转义机制。

由于某些字符在 XML 中具有特殊意义,所以就需要有一种方式来表现它们。例如,某些情况下,< 符号可能真的是要代表小于号,而不是作为元素名的开始符号。显然,仅仅插入这个字符而不做任何转义操作会导致文档不合法,因为处理程序会假定我们是要开启另外一个元素。这一问题的另一个实例是在属性值中需要同时包含双引号和单引号。这里有一个例子,演示了这两个问题:

<badDoc>
  <para>
    I'd really like to use the < character
  </para>
  <note title="On the proper 'use' of the “ character"/>
</badDoc>

XML 中可以使用预定义的实体引用避免这一问题。XML 环境中的单词实体仅仅意味着一个内容单元。术语实体引用意味着,一个象征性的符号表示某个内容单元。XML 预定义了下列实体符号:左尖括号(<),右尖括号(>),撇号('),双引号("),和号(&)。

实体符号以 & 开头,紧随其后的是一个名字(真正意义上用的是这个名字,由 XML 1.0 规范定义),最后以分号(;)结尾。表 A-2 展示了可用于 XML 文档中的 5 个预定义实体。

表A-2:XML 1.0预定义的实体引用

原字符

实体引用

<

&lt;

>

&gt;

'

&apos;

"

&quot;

&

&amp;

下面是用实体引用修订有问题的文档之后的结果:

<badDoc>
  <para>
    I'd really like to use the &lt; character
  </para>
  <note title="On the proper &apos;use&apos;
                of the &quot; character"/>
</badDoc>

在 SVG 中也能使用这些预定义实体;一般来说,实体为我们创建 XML 文档提供了方便。XML 1.0 还允许我们自定义实体,然后在文档中使用这些实体作为“快捷方式”。XML 1.0 规范的第 4 节(http://www.w3.org/TR/REC-xml/#sec-physical-struct)描述了实体的使用。

在 SVG 文档环境中我们还可能找到字符引用。字符引用允许我们通过指定 Unicode 字符集中的位置(这个位置也被称为字符码)来表示某个字符。表 A-3 中的一些例子演示了它的语法。

表A-3:UTF-8字符引用示例

实际字符

字符引用

1

&#49;

A

&#65;

Ñ

&#xD1;

®

&#xAE;

注意,这些字符码可以用十进制或者用 x 做前缀的十六进制表示。

30:00