科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件建立有效的XML文件

建立有效的XML文件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

有效的XML 文件必需符合一组比格式正确更严谨的规则。在本章中,首先你将学习有效的XML文件的基本需求,以及探索制作有效文件所带来的好处。

作者: 来源:中国软件网 2008年6月23日

关键字: 有效 建立 XML 软件

  • 评论
  • 分享微博
  • 分享邮件
 有效的XML 文件必需符合一组比格式正确更严谨的规则。在本章中,首先你将学习有效的XML文件的基本需求,以及探索制作有效文件所带来的好处。接下来,你将学习如何加入所有有效的XML 文件中要求的文件型态宣告。然后呈现在有效的文件中被用来定义元素与属性的指令。最后以一个练习作为结束,该练习是将你在第二章中建立的范例文件进行转换。在下一章中,你将学习如何宣告与使用实体,这是有效的XML 文件中选择性、但却非常有用的要素。

有效的XML 文件的基本条件

    每一份XML 文件都必须是格式正确的,意指它必须符合一组遵从XML 文件规格的最小要求。如果文件不是格式正确的,它不能被视为XML 文件。一个格式正确的XML 文件也可以是有效的XML 文件。而且只要符合两项额外的要求,一个有效的XML 文件也将是格式正确的:
    文件的序文必须包含合适的文件型态宣告,该宣告中包括了文件型态定义(DTD),负责定义文件的结构。
    文件的其余部分必须符合DTD 中所定义的结构。
    在本章及第六章中,你将学习如何建立遵守这两项要求的文件。

格式正确与有效性的限制

    格式正确的限制是一组在XML 规格书中定义,你必须遵从的规则-除了基本的语法要求之外-以用来建立格式正确的文件。因为XML 文件必须是格式正确的,任何违反格式正确限制的状况都会被视为毁灭性错误(fatal error)。当XML 处理器遭遇毁灭性错误时,它会停止文件的正常执行,并且不会企图尝试任何的回复动作。
    有效性限制则是XML 规格书中你必须遵守以建立正确文件的附加规则。因为有效性对XML 文件而言只是选择性的条件,所以违反有效性限制只会被视为普通的错误,与毁灭性错误成对比。当XML 处理器遭遇错误时,它只是简单地报告错误,并试着进行回复。有效性限制是一组建立适当的文件型态宣告以及其DTD 的特殊规则,并且也是建立遵从DTD 中规则文件的一组特殊规则。

制作有效XML 文件的好处

    建立一份有效的XML 文件看起来可能是一件不麻烦的事。你必须先在DTD 中彻底定义文件的结构,并根据所有的DTD 规则来建立文件本身。接着立即加入你所需的元素与属性,看起来似乎简单多了,如同你在前一章格式正确的文件范例中所做的一样。
    然而,如果你想确定你的文件符合特殊的规格或标准集,那么将定义结构的DTD 含括进来,将允许XML 处理器(如在Microsoft Internet Explorer 5 中的处理器)检查你的文件是否符合其结构。换言之,DTD 提供处理器标准的蓝图,让它在进行文件有效性的检查时,可以执行要求的结构并保证你的文件符合需要的标准。如果文件中的任何部分并未遵守DTD 的规格,处理器会显示错误讯息好让你可以修改文件让文件符合规格。制作有效的XML 文件在确保一组相似文件的唯一性时特别有用。事实上,XML 将DTD 定义成「文件类别的文法」。
    例如,假设一家网站出版公司需要它旗下所有的编辑去建立符合一般结构的XML 文件。建立单一的DTD 并将它放在所有的文件中,可以确保这些文件会完全符合那些要求的结构,而且编辑们并不会任意地加入新属性,不会以错误的顺序放置信息,或者将错误的数据型态放到属性中,以及诸如此类的东西。当然,文件必须经过负责检查其有效性限制的处理器检查并正常执行。
    如果文件正要被针对特殊文件结构的订制软件处理时,则含括DTD 并检查其有效性是特别重要的。如果该软件的全部使用者都在他们的XML 文件中使用了共同的DTD,而且如果文件已经针对有效性进行检查,则使用者将可以确定他们的文件会被处理软件所承认。例如,如果一个数学团体正在建立将使用特定软件来显示的数学文件,那么他们需要为他们的文件使用一个共同的DTD,该DTD 定义了必要的结构、元素、属性与其它特性等。
    事实上,在第一章结尾部分所列举的大多数「实际情况」的XML 应用程序,如MathML,是由标准的DTD 组成。这些应用程序的所有使用者会将标准的DTD 含括在XML 文件中,所以检查文件的有效性将确保文件符合应用程序的结构,且可以被任何针对该应用程序所设计的软件识别认可。
提示
    如果你直接在Internet Explorer 5 中开启XML 文件(含有或不含有样式表),Internet Explorer5 处理器都会检查整份文件(包含文件的型态宣告,如果有的话)是否符合格式正确的,并在任何违法状况发生时显示一个毁灭性错误。然而,Internet Explorer 5 处理器并不会检查文件的有效性。 要测试文件的有效性,你可以使用第九章中提供的 「检查XML 文件的有效性」 的有效性检查script 来测试文件。你可能现在就想要读取该章节中提供的指令,好让你能够开始检查你建立XML 文件的有效性。

新增DTD

    文件的型态宣告是一段你必须加到有效XML 文件序文中的XML 标签。它可以放在序文中的任何地方-其它标签之外-后面接着XML 宣告。(回想一下如果你包含了XML 宣告,它必须位在文件的起始部分。)

    文件型态宣告定义了文件的结构。如果你在Internet Explorer 5 中开启一个不含文件型态宣告的文件,Internet Explorer 5 处理器只会检查文件是否为格式正确的。然而,如果你在InternetExplorer 5 中开启一个含有文件型态宣告的文件(参阅下页的 注意 ),处理器将会检查文件的格式正确性与有效性,而且你的文件必须符合文件型态宣告中的所有宣告。例如,你将无法把并未在文件型态宣告区中宣告的元素或属性包含到文件中。而且你所含括的每一个元素与属性必须符合相关宣告中所陈述的规格(例如允许的文件内容或属性允许的型态)。
注意
    只有当你透过HTML 网页来开启文件时(这个技术将在第八章与第九章中学到),InternetExplorer 5 的处理程序才会检查文件的完整性。如果你直接在Internet Explorer 5 中开启XML文件(如同本书中至目前为止所作的,以及第七章与第十章中将要进行的),处理器将会检查文件(包括文件所包括的任何文件型态宣告)的格式正确性,但却不会检查文件是否符合有效性规则,即使文件拥有文件型态宣告也一样。

DTD 的格式

    文件型态宣告拥有下面的一般格式:
<!DOCTYPE Name DTD>
    这里的Name 指定了文件元素的名称。真正的文件元素名称必须精确地与你在这里所输入的名称相符合(有关管理元素名称的规则的描述,请参阅第三章的 <元素解析> )。例如,如果你正为前一节的范例文件建立文件型态宣告,你将使用元素名称INVENTORY:
<!DOCTYPE INVENTORY DTD>
(这还不是完整的文件型态宣告。DTD 仍然必须以真正的内容来替换。)
    DTD 是文件的文件型态定义,内含定义文件的元素、属性,与其它特性的宣告。在下面的章节中,你将看到其格式。
注意
    就像所有的XML 关键词一样,DOCTYPE 必须利用大写字母撰写。

建构一个DTD

    DTD 是由一个([ ),后面接着一连串的标签宣告,再接着一个(])所组成。卷标宣告描述了文件的逻辑结构;也就是,它们定义了文件的元素、属性,与其它特性。下面是一个完整包含DTD与单一标签宣告的完整XML 文件,其中标签宣告定义了文件的一个元素型态-SIMPLE:

    范例中的DTD 指定了文件可以只包含SIMPLE 型态的元素(这是唯一被定义的元素型态),而且该SIMPLE 元素可以拥有任何可能的内容型态(ANY 关键词)。
    DTD 可以包含下列型态的卷标宣告:
    元素型态宣告 。定义了文件可以包含的元素的型态,以及元素的内容与顺序。元素型态宣告将在下一个章节中介绍。
    属性列表宣告 。每一个属性列表宣告定义了可以用在特定元素型态的属性的名字,以及这些属性的数据型态与默认值。本章稍后会详细介绍每一种宣告。
    实体宣告 。你可以使用实体来储存常用的文字区块,或将非XML 的数据包括在文件中。第六章中将讨论实体的相关知识。
    标签宣告 。卷标描述了数据的格式,或负责识别用来处理特定格式的程序。第六章中将讨论标签。
    处理指令 。第四章的<使用处理指令>中已讨论过。
    批注 。第四章的<加入批注>中已讨论过。
    参数实体参照 。上述的任何项目可以被包含在参数实体中,并藉由参数实体参照来加入。到第六章之前,这个指令对你不具任何意义,现在将它含括进来是为了有效性的考量。
注意
    在这个章节(以及下面章节中的范例)中所讨论的DTD 的型态被称为内部的DTD 子集,因为它整个被包含在文件的文件型态宣告中。在本章的结尾附近,你将学习如何使用位在个别档案中的DTD,它被称为外部的DTD 子集。

宣告元素的型态

    在有效的XML文件中,你必须明确地宣告你在文件中使用的每一个元素的型态,将它宣告于DTD的元素型态宣告(element type declaration)中。一个元素型态宣告代表元素型态的名称与允许的元素内容(通常指定子元素可以发生的顺序)。DTD 中的元素型态宣告-类似数据库的规则-安排了文件的整个逻辑结构。即是,元素型态宣告代表文件包含的元素型态、元素的顺序,与元素的内容规格。

元素型态宣告的类型

    元素型态宣告拥有下列的一般格式:
<!ELEMENT Name contentspec>
    这里的Name 是被宣告元素型态的名称(想复习合法元素名称的规则,请参阅第三章中的 <元素解析> )。而contentspec 指的是内容规格(content specification),定义了元素可以包含的东西。下一节描述了你可以使用的不同型态的内容规格。
    下面是一个名为TITLE 的元素型态的宣告,它只能包含字符数据(子元素则不可以):
<!ELEMENT TITLE (#PCDATA)>
    而下面则是一个名为GENERAL 的元素型态的宣告,可以包含任何型态的内容:
<!ELEMENT GENERAL ANY>
    下面的范例是一个内含两个元素型态的有效XML 文件。COLLECTION 元素型态的宣告代表它可以包含一个或多个CD 元素,而且CD 元素型态的宣告指定了它只能包含字符数据。注意,范例文件符合了这些宣告,因而就是有效的:
<?xml version="1.0"?>
<!DOCTYPE COLLECTION
[
<!ELEMENT COLLECTION (CD)+>
<!ELEMENT CD (#PCDATA)>
<!--You can also insert a comment in a DTD.-->
]
>
<COLLECTION>
<CD>Mozart Violin Concertos 1,2,and 3</CD>
<CD>Telemann Trumpet Concertos</CD>
<CD>Handel Concerti Grossi Op.3</CD>
</COLLECTION>
注意
    在给定的文件中你只能宣告特定的元素型态一次。

元素内容的规格

    你可以指定元素的内容-意即,在元素型态宣告的contentspec 部分指定-利用下面四种方式:
    EMPTY 内容 。你必须使用EMPTY 关键词来代表元素必须是空的-意即不能拥有内容。下面就是一个这样的范例:
<!ELEMENT IMAGE EMPTY>
    下面是一个你可以放入文件中的正确IMAGE 元素:
<IMAGE></IMAGE>
<IMAGE />
    ANY 内容 。你必须使用ANY 关键词来表明元素可以拥有任何型式的内容。意即,这种型态的元素可以包含零或多个子元素,利用任何顺序与次数的重复,使用或不使用字符数据。这是最松散的内容规格,而建立的则是不含内容限制的元素型态。下面就是这种宣告的一个例子。
<!ELEMENT MISC ANY>
    元素内容(也称为子内容) 。利用这种型态的内容规格,元素可以包含子元素,但却不能直接包含字符数据。下一节中将描述这个选项。
    混合内容 。利用这种型态的内容规格,元素可以包含任何数量的字符数据,与随意散置的相同型态字符。本章稍后将描述这个选项。

指定元素内容

    如果元素拥有元素内容,它可以只包含特定的子元素,且不含字符数据。在文件中,你可以随意地利用空格符将子元素分开以加强文件的可读性,但处理器将会忽略这些空格符且不会将之传送到应用程序。
    下面的范例XML 文件,它描述了一本书:
<?xml version="1.0"?>
<!DOCTYPE BOOK
[
<!ELEMENT BOOK (TITLE,AUTHOR)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT AUTHOR (#PCDATA)>
]
>
<BOOK>
<TITLE>The Scarlet Letter</TITLE>
<AUTHOR>Nathaniel Hawthorne</AUTHOR>
</BOOK>
    在这份文件中,BOOK 元素型态被宣告成拥有元素内容。在宣告中紧接在元素名称之后的(TITLE、 AUTHOR),称为内容模型(content model)。内容模型代表允许的子元素的型态与其顺序。在这个范例中,内容模型代表BOOK 元素必须恰好拥有一个TITLE 子元素,后面恰好接着一个AUTHOR 子元素。在文件中,处理器将会忽略用来将子元素与BOOK 元素分隔的三行空白。
    内容模型可以拥有下列两种基本格式的任何一种:
    串行 。内容模型的串行格式代表元素必须有一连串的子元素。你可以利用逗号(,)来将子元素型态的名称分开。例如,下面的DTD 代表MOUNTAIN 文件元素必须拥有一个NAME 子元素,后面接着HEIGHT 子元素,后面再接着一个STATE 子元素。
<!DOCTYPE MOUNTAIN
[
<!ELEMENT MOUNTAIN (NAME,HEIGHT,STATE)>
<!ELEMENT NAME (#PCDATA)>
<!ELEMENT HEIGHT (#PCDATA)>
<!ELEMENT STATE (#PCDATA)>
]
>
    因此,下面的文件元素将是有效的:
<MOUNTAIN>
<NAME>Wheeler</NAME>
<HEIGHT>13161</HEIGHT>
<STATE>New Mexico</STATE>
</MOUNTAIN>
    下面的文件元素则不是有效的,因为子元素的顺序并不像宣告中所设定的:
<MOUNTAIN><!--Invalid element!-->
<STATE>New Mexico</STATE>
<NAME>Wheeler</NAME>
<HEIGHT>13161</HEIGHT>
</MOUNTAIN>
    省略子元素或包含超过一个相同的子元素都会造成违法。如你所见,这是一种非常严格的宣告型式。
    选择 。选择格式的内容模型代表元素可以拥有一连串可能的子元素的任何一个,使用「|」字符来区隔。例如,下面的DTD 设定FILM 元素可以包含一个STAR子元素,或NARRATOR 子元素,也可以是INSTRUCTIOR 子元素:
<!DOCTYPE FILM
[
<!ELEMENT FILM (STAR |NARRATOR |INSTRUCTOR)>
<!ELEMENT STAR (#PCDATA)>
<!ELEMENT NARRATOR (#PCDATA)>
<!ELEMENT INSTRUCTOR (#PCDATA)>
]
>
    因此,下面的文件元素是有效的:
<FILM>
<STAR>Robert Redford</STAR>
</FILM>
    这个元素也是:
<FILM>
<NARRATOR>Sir Gregory Parsloe</NARRATOR>
</FILM>
    还有这个也是:
<FILM>
<INSTRUCTOR>Galahad Threepwood</INSTRUCTOR>
</FILM>
    然而,下面的文件元素将造成违法,因为你只能包含一个子元素型态:
<FILM><!--Invalid element!-->
<NARRATOR>Sir Gregory Parsloe</NARRATOR>
<INSTRUCTOR>Galahad Threepwood</INSTRUCTOR>
</FILM>
    你可以借着使用问号(?)、加号(+),或星号(*)来修改这些内容模型的任何一种,这三个符号的意义如下表所述。
字符       含义
?          零个或一个前置项目
+          一个或多个前置项目
*          零个或多个前置项目
    例如,下面的宣告代表你可以包含一个或多个NAME 子元素,而且HEIGHT 子元素是选择性的:
<!ELEMENT MOUNTAIN (NAME+,HEIGHT?,STATE)>
    因此,下面的元素将是正确的:
<MOUNTAIN>
<NAME>Pueblo Peak</NAME>
<NAME>Taos Mountain</NAME>
<STATE>New Mexico</STATE>
</MOUNTAIN>
    再举另一个范例,下面宣告代表你可以包含零个或多个STAR 子元素,或者是一个NARRATOR子元素,或是一个INSTRUCTOR 子元素:
<!ELEMENT FILM (STAR*|NARRATOR |INSTRUCTOR)>
    因此,下面三个元素的每一个都是合法的:
<FILM>
<STAR>Tom Hanks</STAR>
<STAR>Meg Ryan</STAR>
</FILM>
<FILM>
<NARRATOR>Sir Gregory Parsloe</NARRATOR>
</FILM>
<FILM/>
    你也可以使用「?」、「+」,或「*」字符来修改整个内容模型,方法是借着将字符紧接在结束括号之后。例如,下面的宣告让你可以包含一个或多个这三种型态的子元素,任何顺序都可以:
<!ELEMENT FILM (STAR |NARRATOR |INSTRUCTOR)+>
    该宣告让下面的元素变为合法:
<FILM>
<NARRATOR>Bertram Wooster</NARRATOR>
<STAR>Sean Connery</STAR>
<NARRATOR>Plug Basham</NARRATOR>
</FILM>
<FILM>
<STAR>Sean Connery</STAR>
<STAR>Meg Ryan</STAR>
</FILM>
<FILM>
<INSTRUCTOR>Stinker Pike</INSTRUCTOR>
</FILM>
     最后,你可以借着将选择的内容模型套迭在串行模型中,或将串行模型套迭在内容模性中,来建构更复杂的内容模型。例如,下面的DTD 设定了FILM 文件元素必须拥有一个TITLE 子元素;后面接着一个CLASS 子元素,后面再接着一个STAR、NARRATOR,或INSTRUCTOR 子元素:
<!DOCTYPE FILM
[
<!ELEMENT FILM (TITLE,CLASS,(STAR |NARRATOR |INSTRUCTOR))>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT CLASS (#PCDATA)>
<!ELEMENT STAR (#PCDATA)>
<!ELEMENT NARRATOR (#PCDATA)>
<!ELEMENT INSTRUCTOR (#PCDATA)>
]
>
    根据这份DTD,下面的文件元素是合法的
<FILM>
<TITLE>The Net</TITLE>
<CLASS>fictional</CLASS>
<STAR>Sandra Bullock</STAR>
</FILM>
    还有这个也是:
<FILM>
<TITLE>How to Use XML</TITLE>
<CLASS>instructional</CLASS>
<INSTRUCTOR>Penny Donaldson</INSTRUCTOR>
</FILM>

设定混合的内容

    如果元素拥有混合的内容,它可以包含字符数据。而且如果你在宣告中设定一个或多个子元素型态,它可以包含那些子元素的任何一个,以任何的顺序,以及任何次数的重复(零或多个)。换言之,利用混合内容你可以限制子元素的型态,但你无法限制子元素型态出现的顺序或次数,也不能强制特定子元素型态。
    要宣告混合内容的元素型态,你可以使用下列两种内容模型格式的任何一种:
    只有字符数据 。要宣告只包含字符数据的元素型态,使用内容模型(#PCDATA)。例如,下面的宣告让SUBTITLE 元素只能包含字符数据:
<!ELEMENT SUBTITLE (#PCDATA)>
    根据这个宣告,下面两个元素都是有效的:
<SUBTITLE>A New Approach</SUBTITLE>
<SUBTITLE></SUBTITLE>
    注意,在第二个范例中,被宣告成包含字符数据的元素可以包含零个字符-意即,你可以将之设成空白。(利用这种内容模型,混合内容(mixed content)这个词就技术面上而言是种误称。)
注意
    关键词PCDATA 代表已解析过的字符数据。在第三章中你已经学过XML 处理器会解析元素内的字符数据-也就是说,它会扫描文字以搜寻卷标。因此你不能将(<)或(&)符号或字符串(] ] >)当作是字符数据的一部份,因为处理器会将这些字符或串行解释成卷标。然而,你可以使用字符参照或预先定义的实体参照(在第六章中讨论),或CDATA 区段(于第四章中)。
    字符数据加上额外的子元素 。要宣告一个可以包含字符数据加上零个或多个子元素的元素型态,在内容模型中将每一个子元素列在#PCDATA 之后,利用「|」字符来分隔每个项目,并在整个内容模型之后加入星号( * )。在内容模型中每一个元素的名称只能出现一次。例如,下面的宣告允许TITLE 元素可以包含字符数据,另外加上零或多个SUBTITLE 子元素:
<!ELEMENT TITLE (#PCDATA |SUBTITLE)*>
    下面是正确的TITLE 元素,符合上述宣告:
<TITLE>
Moby-Dick
<SUBTITLE>Or,the Whale</SUBTITLE>
</TITLE>
<TITLE>
<SUBTITLE>Or,the Whale</SUBTITLE>
Moby-Dick
</TITLE>
<TITLE>
Moby-Dick
</TITLE>
<TITLE>
<SUBTITLE>Or,the Whale</SUBTITLE>
<SUBTITLE>Another Subtitle</SUBTITLE>
</TITLE>
<TITLE></TITLE>

宣告属性

    在有效的XML 文件中,你必须明确地宣告所有你将和文件元素一起使用的属性。你将借着属性列表宣告(attribute-list declaration)的DTD 标签来定义所有与特定元素相关的属性。这种宣告作了下面这些工作:
    设定与元素相关属性的名称。在有效的文件中,你只能将那些为元素所作的定义包含在元素的起始卷标中。
    设定每个属性的数据型态。
    为每个属性设定该属性是否为必要的。如果属性并不是必要的,属性列表宣告也将指明当属性被省略时,处理器应该要做什么。(例如,宣告可能会提供一个处理器可以使用的预设属性值。)

属性列表宣告的种类

    属性列表宣告拥有下列格式:
<!ATTLIST Name AttDefs>
    这里的Name 是与属性关联元素的型态名称。AttDefs 则是一系列一个或多个属性定义(attributedefinition),每一个负责定义一个属性。
    属性定义拥有下列格式:
Name AttType DefaultDecl
    这里的Name 是属性的名称。(要复习合法属性名称的规则,请参阅第三章中的 <建立属性的规则> 。)AttType 是属性的型态(attribute type),是一种可以被设定到属性的值。(下一节将讨论属性的型态。)而DefaultDecl 是预设宣告(default eclaration),指出属性是否为必要的并提供其它信息。(本章稍后将讨论预设宣告。)
    例如,你可以像这样宣告一个名为FILM 的元素型态:
<!ELEMENT FILM (TITLE,(STAR |NARRATOR |INSTRUCTOR))>
    下面是一个属性列表宣告的范例,宣告了两个属性-名称分别为Class 与Year-是为FILM 元素宣告的:
<!ATTLIST FILM Class CDATA "fictional " Year CDATA ##REQUIRED>
    下面是这个宣告的不同之处:

    你可以为Class 属性指派任何合法的引号包围字符串(CDATA 关键词);如果你将属性从特定元素中省略,它将自动指派默认值「fictional」给处理器。你可以为Year 属性指定任何合法的引号包围字符串;然而,该属性必须在每一个HTML 元素(#REQUIRED 关键词)中被指定一个值,因此它并没有默认值。
    下面这个有效的XML 文件包含了这个属性列表以及FILM 元素:
<?xml version="1.0"?>
<!DOCTYPE FILM
[
<!ELEMENT FILM (TITLE,(STAR |NARRATOR |INSTRUCTOR))>
<!ATTLIST FILM Class CDATA "fictional" Year CDATA
##REQUIRED>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT STAR (#PCDATA)>
<!ELEMENT NARRATOR (#PCDATA)>
<!ELEMENT INSTRUCTOR (#PCDATA)>
]
>
<FILM Year="1948">
<TITLE>The Morning After</TITLE>
<STAR>Morgan Attenbury</STAR>
</FILM>
    在FILM 元素中,Year 属性的指定值为「1948」。 Class 属性被省略;然而,因为这个属性拥有默认值(「fictional」),它会被指派默认值,如同你包含该属性并为它输入该值。
注意
    如果你为一个元素型态包含了多个属性列表宣告,两个宣告的内容会被合并。如果一个拥有给定名称的属性为同一个元素被宣告一次以上,第一个宣告将被使用而第二个会被忽略。(当文件拥有内部与外部的DTD 子集时,多个属性列表宣告是很普遍的,本章稍后将会介绍。)

属性的型态

    属性列表是属性定义中第二个必要的组件。它指定了何种值你可以设定到文件的属性中。

    你可以利用下面三种方式来指定属性的型态:
    字符串型态 。字符串型态属性可以被指定任成何引号包围的字符串(也称为literal(字义)),这种引号包围的字符串必须符合第三章中 <合法属性值的规则> 章节中所介绍的规则。你会使用关键词CDATA 来宣告一个字符串型态属性,如同下面范例中的Class 的属性定义:
<!ATTLIST FILM Class CDATA "fictional">
    Tokenized 型态 。你可以指定到Tokenized 型态属性的值必须受到数种限制,将在下一节中介绍。
    列举型态 。你可以为列举型态属性选择列表中的一个值。本章稍后将讨论这种型态。

设定Tokenized 型态

    就像任何的属性值一样,你为Tokenized 型态指定的值必须是一个符合第三章中 <合法属性值的规则> 章节中所介绍的规则的引号包围字符串。
    另外,该值必须符合你在属性定义中借着适当关键词所指定的特殊限制。例如,在下面的XML文件中,StockCode 属性借着使用ID 关键词被定义成tokenized 型态。(ID 是唯一你可以用来宣告tokenized 型态的关键词)这个关键词代表对于每一个元素、属性都必须被指定一个唯一的值。(例如,将股票号码「S021」设定到两个ITEM 元素中将会造成违法。)
<?xml version="1.0"?>
<!DOCTYPE INVENTORY
[
<!ELEMENT INVENTORY (ITEM*)>
<!ELEMENT ITEM (#PCDATA)>
<!ATTLIST ITEM StockCode ID #REQUIRED>
]
>
<INVENTORY>
<!--Each ITEM must have a different StockCode value.-->
<ITEM StockCode="S021">Peach Tea Pot</ITEM>
<ITEM StockCode="S034">Electric Coffee Grinder</ITEM>
<ITEM StockCode="S086">Candy Thermometer</ITEM>
</INVENTORY>
    下面是你可以用来定义tokenized 型态属性的关键词,以及加诸在属性值上限制的完整列表:
    ID 在每一个元素中属性都必须拥有一个唯一值。该值必须以字母或底线(_)开始,后面接着零或多个字母、数字、句点(.)、连字号(-),或底线(_)。它也可以包含单一个冒号(:),除了不能放在第一个字符位置外。特殊的元素属性只能拥有一个ID 型态属性,而且属性的预设宣告必须是#REQUIRED 或#IMPLIED(本章稍后将会介绍)。你可以在上面给定的INVENTORY 文件中看到这种型态属性的范例。
    IDREF 属性值必须与文件中元素内的某些ID 型态属性的值相符合。换言之,这种型态的属性会参考另一个属性的唯一识别代号。例如,你可以加入一个名为GoesWith 的IDREF 属性到ITEM 元素中:
<!ELEMENT ITEM (#PCDATA)>
<!ATTLIST ITEM StockCode ID #REQUIRED GoesWith IDREF #IMPLIED>
    接着你可以使用这个属性来参考另一个ITEM 元素,如下所示:
<ITEM StockCode="S034">Electric Coffee Grinder</ITEM>
<ITEM StockCode="S047" GoesWith="S034">
Coffee Grinder Brush
</ITEM>
    IDREFS 这种属性就像IDREF 型态,除了它的值可以参考数个识别代号-以空格符分隔-全部包含在引号字符串内。例如,如果你像这样为GoesWith 属性指定IDREFS 型态:
<!ATTLIST ITEM StockCode ID #REQUIRED GoesWith IDREFS#IMPLIED>
    你可以用它来参考数个其它元素:
<ITEM StockCode="S034">Electric Coffee Grinder</ITEM>
<ITEM StockCode="S039">
1 pound Breakfast Blend Coffee Beans
</ITEM>
<ITEM StockCode="S047" GoesWith="S034 S039">
Coffee Grinder Brush
</ITEM>
    ENTITY 属性值必须与宣告于DTD 中未解析的实体相符合。未解析实体会参考一个外部档案,通常会是一个储存非XML 数据的档案。笔者将在第六章中讨论实体。
    例如,在DTD 中你可能会宣告一个名为IMAGE 的元素来呈现图形影像,与一个名为Source 的ENTITY 型态属性来代表图形数据的来源,像这样:
<!ELEMENT IMAGE EMPTY>
<!ATTLIST IMAGE Source ENTITY #REQUIRED>
    如果你宣告一个名为Logo 的未解析实体(使用的技术你将在第六章中学到),内含影像的图形数据,你可以将该实体指定到文件中IMAGE 元素的Source 属性,如下所示:
<IMAGE Source="Logo" />
    ENTITIES 这种型态就像ENTITY 型态,除了其值可以包含数个未解析实体的名称-以空格符隔开-全部被包含在引号字符串中。例如,如果你将Source 属性设定成ENTITIES 型态,如下所示:
<!ELEMENT IMAGE EMPTY>
<!ATTLIST IMAGE Source ENTITIES #REQUIRED>
    你可以用它来参考数个未解析实体(或许该实体以另一种格式储存图形数据),如下所示:
<IMAGE Source="LogoGif LogoBmp" />
    (这个范例假设LogoGif 与LogoBmp 为DTD 中宣告的未解析实体的名称,其中使用的技术将在第六章中讨论。)
    NMTOKEN 其值为name token,这是一个由一个或多个字母、数字、句点(.)、连字号(-),或底线(_)所组成的名称。name token 也可以包含冒号(:),只要不是在第一个字符位置就可以了。例如,如果你将ISBN 属性指定成NMTOKEN型态,如下所示:
<!ELEMENT BOOK (#PCDATA)>
<!ATTLIST BOOK ISBN NMTOKEN #REQUIRED>
    你可以为它指定一个以数字起头的值(对于NMTOKEN与NMTOKENS型态而言,起始字符是数字字符是被允许的,但对于其它tokenized 型态则不被允许):
<BOOK ISBN="9-99999-999-9">The Portrait of a Lady</BOOK>
    NMTOKENS 这种型态的属性就像NMTOKEN 型态,除了其值可以包含数个name tokens-以空格符隔开-全部被包含在引号字符串中。例如,如果你将Codes 属性设定成NMTOKENS 型态,如下所示:
<!ELEMENT SHIRT (#PCDATA)>
<!ATTLIST SHIRT Codes NMTOKENS #REQUIRED>
    你可以为它赋予数个name token 值:
<SHIRT Codes="38 21 97">long sleeve Henley</SHIRT>

设定列举型态

    就像其它属性值一样,你为列举型态的属性所指定的值必须是一个引号包围的字符串,这种引号包围的字符串必须符合第三章 <合法属性值的规则> 一节中所介绍的规则。另外,该值必须符合你在属性型态规格中所列名称的一个,让你可以拥有下列两种型式的一种:
    一个开放的圆括号,后面接着一个name tokens 列表,以「|」字符作分隔,后面再接着结束的括号。如前所述,name token 是由一个或多个字母、数字、句点(.)、连字号(-),或底线(_)所组成的名称。它也可以包含冒号(:),只要不是在第一个字符位置就可以了。例如,如果你想限制Class 属性的值为「fictional」、「instructional」、或「documentary」,你可以将这个属性定义成列举型态,如下所示:
<!ATTLIST FILM
Class (fictional |instructional |documentary)
"fictional">
    下面是展示Class 属性用途的有效XML 文件:
<?xml version="1.0"?>
<!DOCTYPE FILM
[
<!ELEMENT FILM (TITLE,(STAR |NARRATOR
|INSTRUCTOR))>
<!ATTLIST FILM
Class
(fictional|instructional|documentary)"fictional">
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT STAR (#PCDATA)>
<!ELEMENT NARRATOR (#PCDATA)>
<!ELEMENT INSTRUCTOR (#PCDATA)>
]
>
<FILM Class="instructional">
<TITLE>The Use and Care of XML</TITLE>
<NARRATOR>Michael Young</NARRATOR>
</FILM>
    如果你省略Class 属性,它会被指定为默认值「fictional」。为Class 属性指定一个非「fictional」、「in-structional」,或「documentary」的值将会发生违反有效性的错误。
    关键词NOTATION 后面接着空白,然后再接着一个开始的括号,再接着一个标签名称列表,以「|」字符作分隔,后面再接着结束的括号。这些名称必须明确地符合DTD 中所宣告的标签名称。卷标描述了数据格式或定义了被用来处理特定格式的程序。第六章将会讨论标签。例如,假设HTML、SGML,与RTF 标签被宣告于DTD 中(如下所示),你可以限制Format 属性的值为这些标签名称中的任何一个:
<!ELEMENT EXAMPLE_DOCUMENT (#PCDATA)>
<!ATTLIST EXAMPLE_DOCUMENTFormat NOTATION (HTML|SGML|RTF)#REQUIRED>
    你可以接着使用Format 元素来指出特定EXAMPLE_DOCUMENT 元素的格式,如下所示;
<EXAMPLE_DOCUMENT Format="HTML">
<![CDATA[
<HTML>
<HEAD>
<TITLE>Mike''s Home Page</TITLE>
</HEAD>
<BODY>
<P>Welcome!</P>
</BODY>
</HTML>
] ]>
</EXAMPLE_DOCUMENT>
    若是将Format 属性的值设定成「HTML」、「SGML」,或「RTF」以外的值,将会造成有效性错误。(注意这里CDATA 区段的使用,让你可以在元素的字符数据中随意地使用(<)字符。)

预设宣告

    预设宣告是第三个也是最后一个属性定义的必要组件。它指定了属性是否是必要的,以及如果属性不是必要的,会指出当属性被省略了处理器应该做什么。例如,宣告可能会提供一个预设属性值,当属性被省略时,处理器应该使用该值。

    预设的宣告拥有四个可能的格式:
    #REQUIRED 利用这种格式,你必须为相关型态的每一个元素设定属性值。例如,下面的宣告指明你应该为文件中每一个FILM 元素的起始卷标内的Class 属性指定属性值:
<!ATTLIST FILM Class CDATA #REQUIRED>
    #IMPLIED 这种格式指出你可以包含属性或从关联型态的元素中省略该属性,而且如果你省略了该属性,没有默认值可以提供给处理器。(这种「暗示(implies)」而不是「指定(states)」的值会导致应用程序使用其专有的默认值-因此是name。)例如,下面的宣告指出为FILM 元素中的Class 属性指定属性值是随意的,而且文件并不会提供预设的Class 属性值:
<!ATTLIST FILM Class CDATA #IMPLIED>
    AttValue 其中AttValue 是预设的属性值。利用这种格式,你可以包含属性或从关联型态的属性中删除该属性。而且如果你省略了该属性,处理器将会使用默认值,如同你已经为属性包含该属性并输入属性值。
    当然,你所指定的默认值必须符合指定的属性型态。例如,下列的宣告指定一个默认值为「fictional」到Class 属性中:
<!ATTLIST FILM Class CDATA"fictional">
    利用这个宣告,下面两个元素是相同的:
<FILM>The Graduate</FILM>
<FILM Class="fictional">The Graduate</FILM>
    #FIXED AttValue 其中AttValue 是预设的属性值。利用这种格式,你可以将属性包含于相关型式的元素或从元素中将属性省略。如果你将属性删去,处理器将使用指定的默认值;如果你包含某个属性,你必须为它指定默认值。(因为你只能指定默认值,所以不会有强制性因素要求将属性的设定含括于元素中,除了要将文件变得更清楚好方便阅读。)例如,下面的宣告指定一个固定的默认值到Class
属性:
<!ATTLIST FILM Class CDATA #FIXED "documentary">
    利用这个宣告,下面两个相等的元素都是有效的:
<FILM>The Making of XML</FILM>
<FILM Class="documentary">The Making of XML</FILM>
    而下面的元素则不是有效的:
<!--Invalid element!-->
<FILM Class="instructional">The Making of XML</FILM>

使用外部的DTD 子集

    到目前为止,你在本章中所见到的文件型态定义都是完全包含在文件的文件型态宣告中。这种型式的DTD 被称为内部的DTD 子集(internal DTD subset)。
    另一种替代的方法是,你可以将DTD 的全部或部分放在个别的档案,并从文件型态的宣告中参考该档案。包含在个别档案中的DTD-或DTD 的部分-被称为外部DTD 子集(external DTDsubset)。
注意
    使用外部DTD 子集主要是对整个文件群组所使用的共同DTD 有利。每一份文件可以参考单一DTD 檔(或该档案的复制)当作外部的DTD 子集。这将省去必须将DTD 元素复制到文件才能使用的功夫,并且让DTD 更容易被维护。(你只需修改该DTD 档-或该档的任何复制-而不是必须编辑所有使用该DTD 文件的档案。)如第一章提到的,许多标准的XML 应用程序,都是以一个包含在所有符合该应用程序的XML 文件中的共同DTD 为基础。请参考第一章中的 <标准的XML 应用程序> 与 <XML 在实际例子中的使用概况> 。

仅仅使用外部DTD 子集

    要只使用外部的DTD 子集,可将包含在中括号([ ])字符中的卷标宣告区块删除,而以关键词SYSTEM 后面接着一个包含该DTD 的个别档案位置的引号内叙述来取代。例如,你在本章稍早所见到的SIMPLE 文件,它拥有一个内部的DTD 子集:
<?xml version="1.0"?>
<!DOCTYPE SIMPLE
[
<!ELEMENT SIMPLE ANY>
]
>
<SIMPLE>This is an extremely simplistic XML document.</SIMPLE>
    如果文件使用外部DTD 子集,则它出现的样子应该像这样:
<?xml version="1.0"?>
<!DOCTYPE SIMPLE SYSTEM"Simple.dtd">
<SIMPLE>This is an extremely simplistic XML document.</SIMPLE>
    而Simple.dtd 档案将会拥有下面内容:
<!ELEMENT SIMPLE ANY>
    包含了外部DTD 子集的档案可以包含任何的卷标宣告,这些卷标宣告可以包含在内部的DTD子集中。本章稍早章节<建构一个DTD>中已讨论过这些相关议题。
    档案位置的描述(在范例中是指Simple.dtd 档案)被称为系统literal。它可以被单引号('')或双引号(")包围,而且可以包含除了被用来包围该字符串的引号之外的任何字符。
    系统literal 指定了包含外部DTD 子集档案的统一资源识别代号(uniform resource identifier,URI)。目前,URI 本质上是与标准的因特网地址,被称为统一资源定位器(Uniform Re-sourceLocator)或URL。你可以使用完全合法的URI,如下所示:
<!DOCTYPE SIMPLE SYSTEM "http://bogus.com/dtds/Simple.dtd">
    或者,你可以使用部分的URI,该URI 指定了相对于包含该XML 文件位置的相对位置,如下所示:
<!DOCTYPE SIMPLE SYSTEM "Simple.dtd">
注意
    URI 是一个崭新、具高度弹性用来安排资源位置的系统标记。URI 的一种型态就是URL(统一资源定位器),通常用在因特网中(例如, http://mspress.microsoft.com/ )。在将来,URI 将会包含其它用来安排资源的标记型式。然而,这些都还在发展中。
    XML 文件中的相对URI 的运作模式就像HTML 网页中的相对URL 一样。在第二个范例中,如果XML 文件的完整URI 是http://bogus.com/documents/Simple.xml ,「Simple.dtd」将会参照到 http://bogus.com/documents/Simple.dtd 。同样地,如果XML 文件是位在file:///C:\XML Stepby Step\Example Code\Simple.xml,「Simple.dtd」将会参照到file:///C:\XML Step by
Step\Example Code\Simple.dtd。

使用外部DTD 子集与内部DTD 子集

    要一起使用外部DTD 子集与内部的DTD 子集,将SYSTEM 关键词与提供外部DTD 子集档案的系统literal 包含在一起,后面接着包含在中括号([ ])字符中的内部DTD 子集的标签宣告。
    下面是一个包含内部与外部DTD 子集的简单XML 文件的范例:
<?xml version="1.0"?>
<!DOCTYPE BOOK SYSTEM "Book.dtd"
[
<!ATTLIST BOOK ISBN CDATA #IMPLIED Year CDATA"2000">
<!ELEMENT TITLE (#PCDATA)>
]
>
<BOOK Year="1998">
<TITLE>The Scarlet Letter</TITLE>
</BOOK>
    下面是包含外部DTD 子集的档案Book.dtd 的内容:
<!ELEMENT BOOK ANY>
<!ATTLIST BOOK ISBN NMTOKEN #REQUIRED>
    当你包含了内部与外部DTD 子集,下面是XML 处理器如何结合内部与外部子集的内容:
    通常,它会合并两种子集的内容来组成完整的DTD。在范例中,作为结果的合并DTD 定义了两个元素,TITLE 与BOOK,以及BOOK 元素的两个属性-ISBN 与YEAR。
    然而,如果相同名称的属性与元素型态被宣告超过一次以上,XML 处理器会使用第一个宣告并将后面的宣告忽略。(这也将适用于实体的重复宣告,第六章中将会讨论。)
    内部的DTD 子集被认为比外部的DTD 子集(即使是外部子集的参照先出现在文件型态的宣告区中)具有较高的优先权。因此,定义在内部的任何属性(或实体)的地位高于宣告于外部子集中相同的名称与元素型态。在范例中,XML 处理器会认为ISBN 属性拥有CDATA 型态与#IMPLIED 默认值,因此下面的元素(省去ISBN)是正确的:
<BOOK Year="1850">
<TITLE>The Scarlet Letter</TITLE>
</BOOK>
注意
    虽然XML 处理器简单地将属性与实体的重复宣告省略,元素的重复宣告(即使是以相同方法宣告)还是违法的。
    XML 处理器结合内部与外部DTD 子集的方法让你可以将普通的DTD 子集(就像XML 应用程序,MathML 所提供的DTD 子集)当作外部DTD 子集使用,但接着藉由包含一个内部子集来为目前的文件定制(或子集合化)DTD。你的内部子集可以加入元素、属性,或实体-而且该子集还可以改变属性或实体的定义。

外部DTD 子集中的条件式忽略区段

    你可以借着使用IGNORE 区段来让XML 处理器忽略外部DTD 子集的部分。例如,当设计文件时你可能会使用IGNORE 区段,来暂时撤销一个选择性的标签宣告区块,如此你就不必删除该行而又在稍后需要重新输入该行。(如果你刚好是个程序设计人员,你将会发现这个技术很像「批注化」你想暂时忽略的程序区块。)IGNORE 区段以字符<![IGNORE[起始,且以]]>作为结束。
    下面是一个包含IGNORE 区段的完整外部DTD 子集的范例:

    如果你想暂时使IGNORE 区段中的标签宣告的区块再度启动,你可以简单地将关键词IGNORE换成INCLUDE,而不必把限定字符(<![、 [与]]>)删除,如下面范例所示:
<![INCLUDE [
<!--an optional block of markup declarations
that are temporarily reactivated -->
<!ATTLIST BOOK Category CDATA "fiction">
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT AUTHOR (#PCDATA)>
]]>
    接着你可以借着将IGNORE 关键词放回来迅速地再度撤销该区段。一个套迭于IGNORE 区段中的IGNORE 区段将会被忽略。
注意
    你只能在外部DTD 子集或外部的参数实体中使用IGNORE 与INCLUDE 区段。(如同你将在第六章学到的,外部的参数实体会参照个别档案-就像外部DTD 子集-包含了标签宣告。)

将格式正确的文件转换成有效的文件

    在本章中,你将借着将格式正确的文件转换成有效的文件,获得某些实际动手操作的经验,以及本章所要呈现的观念。你将修改你在第二章中所建立 Inventory.xml 文件来让文件变得完整。你也将加入一个新元素与两个属性来获得你在本章中学到的额外技术的体验。

制作有效的文件

    1. 在文字编辑器中, 开启 你将在第二章中建立的 Inventory.xml 文件。(于列表2-1 中)
    2. 于名为INVENTORY 的文件元素之上-输入下面的文件型态宣告:
3. <!DOCTYPE INVENTORY
4. [
5. <!ELEMENT INVENTORY (BOOK)*>
6.
7. <!ELEMENT BOOK
(TITLE,AUTHOR,BINDING,PAGES,PRICE)>
8. <!ATTLIST BOOK InStock
(yes|no)#REQUIRED>
9.
10. <!ELEMENT TITLE (#PCDATA |SUBTITLE)*>
11.
12. <!ELEMENT SUBTITLE (#PCDATA)>
13.
14. <!ELEMENT AUTHOR (#PCDATA)>
15. <!ATTLIST AUTHOR Born CDATA #IMPLIED>
16.
17. <!ELEMENT BINDING (#PCDATA)>
18.
19. <!ELEMENT PAGES (#PCDATA)>
20.
21. <!ELEMENT PRICE (#PCDATA)>
22. ]
>
提示
    在执行这些练习中指定的修改,你可以参考位于本章结尾 列表5-1 中所包含修改过的完整文件。
    请注意,紧接在DOCTYPE 关键词后面的名称必须符合文件元素的名称-INVENTORY。该DTD 仅由内部子集组成,定义了文件的元素与属性如下:
    文件元素INVENTORY,拥有元素的内容。它可以包含零或多个BOOK子元素。
    BOOK 元素也可以拥有元素内容。它必须恰好只包含一个下列的元素,依照列于元素宣告的顺序:TITLE、 AUTHOR、BINDING、PAGES 与PRICE。
    TITLE 元素拥有混合的内容。它可以包含字符数据,其间散置零或多个SUBTITLE 元素。
    每一个AUTHOR、BINDING、PAGES,与PRICE 元素也拥有混合的内容。然而,这些元素可以只包含字符数据且不含子元素。
    BOOK 元素拥有一个列举型态的属性,名为InStock,它是一个必要的属性,可以指定值为「yes」或「no」。
    AUTHOR 元素拥有一个名为Born 的字符串型态属性,它是一个选择性的属性且没有默认值。
    23. 为Moby-Dick 书籍加入下列的SUBTITLE 子元素到TITLE 元素中:
24. <BOOK>
25. <TITLE>Moby-Dick
26. <SUBTITLE>Or,the Whale</SUBTITLE>
</TITLE>
    27. 加入必要的InStock 属性到每一个BOOK 元素中,将其值指定成「yes」或「no」,如下面范例所示;
28. <BOOK InStock="yes">
29. <TITLE>The Adventures of Huckleberry
Finn</TITLE>
30. <AUTHOR>Mark Twain</AUTHOR>
31. <BINDING>mass market paperback</BINDING>
32. <PAGES>298</PAGES>
33. <PRICE>$5.49</PRICE>
</BOOK>
    34. 将选择性的Born 元素加到一个或多个元素中。虽然你可以为该属性指定任何的引号包围字符串,但是属性的目的是储存作家(AUTHOR)的生日。如下所示:
<AUTHOR Born="1835">Mark Twain</AUTHOR>
    35. 要表现出你指定的新档名,将位于文件起始部分的批注,从:
<!--File Name:Inventory.xml -->
    改成:
<!--File Name:Inventory Valid.xml -->
    36. 使用文字编辑器的 另存新文件 指令将修改过的文件储存于档案 InventoryValid.xml 中。
    完整的XML 文件显示于列表5-1 中(你可在随书光盘的 Inventory Valid.xml 档案中找到)。
Inventory Valid.xml
<?xml version="1.0"?>
<!--File Name:Inventory Valid.xml -->
<!DOCTYPE INVENTORY
[
<!ELEMENT INVENTORY (BOOK)*>
<!ELEMENT BOOK
(TITLE,AUTHOR,BINDING,PAGES,PRICE)>
<!ATTLIST BOOK InStock (yes|no)#REQUIRED>
<!ELEMENT TITLE (#PCDATA |SUBTITLE)*>
<!ELEMENT SUBTITLE (#PCDATA)>
<!ELEMENT AUTHOR (#PCDATA)>
<!ATTLIST AUTHOR Born CDATA #IMPLIED>
<!ELEMENT BINDING (#PCDATA)>
<!ELEMENT PAGES (#PCDATA)>
<!ELEMENT PRICE (#PCDATA)>
]
>
<INVENTORY>
<BOOK InStock="yes">
<TITLE>The Adventures of Huckleberry
Finn</TITLE>
<AUTHOR Born="1835">Mark Twain</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>298</PAGES>
<PRICE>$5.49</PRICE>
</BOOK>
<BOOK InStock="no">
<TITLE>Leaves of Grass</TITLE>
<AUTHOR Born="1819">Walt Whitman</AUTHOR>
<BINDING>hardcover</BINDING>
<PAGES>462</PAGES>
<PRICE>$7.75</PRICE>
</BOOK>
<BOOK InStock="yes">
<TITLE>The Legend of Sleepy Hollow</TITLE>
<AUTHOR>Washington Irving</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>98</PAGES>
<PRICE>$2.95</PRICE>
</BOOK>
<BOOK InStock="yes">
<TITLE>The Marble Faun</TITLE>
<AUTHOR Born="1804">Nathaniel
Hawthorne</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>473</PAGES>
<PRICE>$10.95</PRICE>
</BOOK>
<BOOK InStock="no">
<TITLE>Moby-Dick
<SUBTITLE>Or,the Whale</SUBTITLE>
</TITLE>
<AUTHOR Born="1819">Herman Melville</AUTHOR>
<BINDING>hardcover</BINDING>
<PAGES>724</PAGES>
<PRICE>$9.95</PRICE>
</BOOK>
<BOOK InStock="yes">
<TITLE>The Portrait of a Lady</TITLE>
<AUTHOR>Henry James</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>256</PAGES>
<PRICE>$4.95</PRICE>
</BOOK>
<BOOK InStock="yes">
<TITLE>The Scarlet Letter</TITLE>
<AUTHOR>Nathaniel Hawthorne</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>253</PAGES>
<PRICE>$4.25</PRICE>
</BOOK>
<BOOK InStock="no">
<TITLE>The Turn of the Screw</TITLE>
<AUTHOR>Henry James</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>384</PAGES>
<PRICE>$3.35</PRICE>
</BOOK>
</INVENTORY>
    37. 如果你想要测试文件的有效性,可以使用第九章 <检查XML 文件的有效性> 中所给定的XML 有效性测试 script。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章