1.DTD - XML 建立主组件群(blocks) 像<body>....</body>之类的标签是XML和HTML文件的主组件群(blocks)。 1.1XML文件的组件群 从DTD来看,所有的XML文件(和HTML文件)都是由接下来的简单组件群组成的:Elements元素;Attributes 属性;Entities实体;PCDATA 被解析的字符数据(Parsed Character Data);CDATA 字符数据值(Character Data)。下面是每个组件群的简短解释。 1.2元素(Elements) 元素是XML和HTML文件的主组件群(main building blocks)。HTML元素的实例是"body" 和"table"。XML元素实例是"note" 和"message"。元素可以包括文本、其它元素或者空值。空值html元素的实例是"hr", "br" 和"img"。 例如: <body>body text in between</body> <message>some message in between</message> 1.3属性(Attributes) 属性提供关于元素的额外信息(extra information about elements)。属性总是置于元素的开始标签里面。属性一般是以“名称(name)/值(value)”这样的形势一对对的出现。下面的“img”元素就是关于源文件的补充信息: <img src="computer.gif" /> 元素名称是“img”。属性名称“src”。属性值是"computer.gif"。因为元素自身是空值,所以它是以“/”结束的。 1.4实体(Entities) 实体是对于定义普通文件(define common text)的变量。实体参数是定义实体的参数。很多人都知道HTML实体参数:" "。这里的"no-breaking-space"实体是在HTML中用来在文本中插入一个额外空间的。当XML剖析器解析文件时,实体就会得到扩展。下面(表1)的实体是在XML中预定的: 表 1 字符 字符实体 & &或& ' '或' > >或> < <或< " "或" 1.5 PCDATA PCDATA的意思是被解析的字符数据。把字符数据当作XML元素的开始标签与结束标签之间的文本。剖析器会分析PCDATA文本。文本中的标签会被当作标示的字体,实体将会扩展。 1.6 CDATA CDATA也是字符数据的意思。剖析器不会解析CDATA文本。文本中的标签不会作为标示字体,实体也将不会得到扩展。 2.元素定义 2.1元素声明 元素声明语法如下: <!ELEMENT name content> 其中,name是一个标准的XML标记的名字。Centent由以下三种之一组成: ①关键字EMPTY; ②关键字ANY; ③描述包含在本元素中的子元素的顺序和重复次数的内容模型。 2.2元素内容类型(Element Content Model) 元素内容通常有五种类型:EMPTY、ANY、#PCDATA、子元素型和混合型。 2.2.1 EMPTY类型 EMPTY用于定义空元素,该元素只可能有属性而不会有字符数据或子元素。其形式为<swt/>或<swt></swt>。声明空元素的语法如下: <!ELEMENT emptyelement EMPTY> 2.2.2 ANY类型 该元素可以包含DTD中定义的其他任何元素或已编译的字符数据。声明该元素的语法如下: <!ELEMENT anyelement ANY> 2.2.3 #PCDATA类型 不包含其它任何元素而只包含字符数据的元素,用关键字#PCDATA进行定义,它代表“已编译的字符数据(parsed character data)”。PCDATA可以包含除标记以外的一切字符,包括数字、字母和符号等。被定义为包含PCDATA的元素不能包含任何其它子元素。示例如下: <!ELEMENT title(#PCDATA)> 2.2.4 子元素类型 元素可以包含一系列的子元素,子元素内容模型用于指定某个元素可以包含哪些子元素,如: <!ELEMENT message(header,body,signature,footer)>//message元素包含四个子元素,依次是header、body、signature和footer元素。 根据子元素间的关系,子元素内容模型可以有两种可能的结构:序列和选择。 ①序列。其所有子元素必须出现且仅出现一次,这种结果成为序列。使用序列时应注意,首先,序列中不能出现#PCDATA;其次,子元素自身还可以包含其它子元素。 ②选择。元素间的选择可以进行如下声明: <!ELEMENT elem(subelem1|subelem2|subelem3)>//将子元素用竖线进行分隔,表明elem元素的子元素为subelem1、subelem2和subelem3三者之一,但不能同时包含其中的两个或三个子元素。 序列和选择这两种结构可以结合使用。 2.2.5 混合类型 若某元素既包含子元素又包含已编译的字符数据,则该元素具有混合内容。其声明如下: <!ELEMENT pick(#PCDATA|one|two|three)*> 为避免产生错误,混合内容元素的声明必须遵循这一格式。即采用单一的一组可选项,以#PCDATA开始,后面是混合内容中可能出现的子元素类型,每种只需声明一次。除此之外,“*”必须放在右括号之后。下面的声明是错误的: <!ELEMENT pick(one|#PCDATA|two*|three)> 2.3元素出现次数指示符(Element Occurrence Indicator)见表2 表 2 符号 代表标记出现的次数 ? 不出现或只出现一次 * 不出现或可出现多次 + 必须出现一次以上 无符号 只能出现一次 3.属性定义 3.1属性声明 属性声明的语法如下: <!ATTLIST Element_name Attribute_name Type Defualt_value> 其中,ATTLIST关键字用来定义元素所具有的属性,Element_name是元素名,Attribute_name是该元素所具有的属性名,Type是属性的类型,Defualt_value是属性的默认值。注意:在一个给定的元素中不能有两个属性同名;若属性值中含有双撇号,则该属性值应用单撇号括起来。如: <job comments=’He said,”I can paint only red door” ’>Door Painter</job> 3.2 属性类型 在XML中共有10种属性类型(attribute-type):(见表3) 表 3 属性值类别 描述 CDATA 属性值仅仅是一般的文字。与#PCDATA元素声明类似。 <!ATTLIST AnElem attr CDATA #REQUIRED> Enumerated 列出该属性的取值范围,一次只能有一个属性值能够赋予属性。 <!ATTLIST play position (center|forward|defense) ”center”> NMTOKEN 表示属性值只能由字母或下划线_开始,之后是字母、数字、下划线、短横线或圆点,且不能含有空格。 NMTOKENS 表示属性值能够由多个nmtoken组成,每个nmtoken之间用空格隔开。 ID ID类型用于标识文档中的元素。该属性在xml文件中是唯一的。同时,每个元素最多只能具有一个ID类型的属性。 <!ALLTIST author authorID ID #REQUIRED > IDREF/ IDREFS IDREF表示该属性值是参考了另一个id属性;IDREFS表示该属性值是参考了多个id属性,这些id属性的值用空格隔开。 DTD定义: <!ELEMENT bookInfo(publishers,authors,books)> <!ELEMENT publishers(publisher+)> <!ELEMENT publisher(pname,address)> <!ATTLIST publisher publisherID ID #REQUIRED> <!ELEMENT pname(#PCDATA)> <!ELEMENT address(#PCDATA)> <!ELEMENT authors(author+)> <!ELEMENT author(aname,age,sex)> <!ATTLIST author authorID ID #REQUIRED> <!ELEMENT aname(#PCDATA)> <!ELEMENT age(#PCDATA)> <!ELEMENT sex(#PCDATA)> <!ELEMENT books(book*)> <!ELEMENT book(title,price,year)> <!ATTLIST book publisher IDREF #REQUIRED author IDREFS #REQUIRED> <!ELEMENT title(#PCDATA)> <!ELEMENT price(#PCDATA)> <!ELEMENT year(#PCDATA)> 对应的XML文档: <bookInfo> <publishers> <publisher publisherID=”p001”> <pname>tsinghua university press</pname> <address>Beijing</address> </publisher> <publisher publisherID=”p002”> <pname>electronic industy press</pname> <address>Beijing</address> </publisher> </publishers> <authors> <author authorID=”a001”> <aname>Mary</aname> <age>34</age> <sex>male</sex> </author> <author authored=”a002”> <aname>Tom</aname> <age>39</age> <sex>female</sex> </author> </authors> <books> <book publisher=”p001” author=”a001 a002”> <title>XML</title> <price>22</price> <year>2007</year> </book> </books> </bookInfo> ENTITY 表示该属性的设定值是一个外部实体(entity),如一个图片文件。 ENTITYS 该属性值包含了多个外部entity,不同的entity之间用空格隔开。 NOTATION 属性值是在DTD中声明过的notation(声明用什么应用软件解读某些二进制文件,如图片)。 <!NOTATION gif SYSTEM “GIF_Viewer”> <!NOTATION jpg SYSTEM “JPG_Viewer”> <!NOTATION png SYSTEM “PNG_Viewer”> <!ELEMENT img (#PCDATA)> <!ATTLIST img src CDATA #REQUIRED NOTATION(png|jpg|gif)#REQUIRED > //其中,type属性的值可以为png、jpg和gif之一,且每个值均与一个相应的<!NOTATION>声明相对应。 3.3 属性默认值 属性声明可以给属性指定一个默认值,使得当在XML文档中未明确地指定该属性的值时,XML处理器会将此默认值作为该属性的值。属性的默认值可用#REQUIRED、#IMPLIED、#FIXED和字符串定义,见表4。 表4 属性内定值 描述 #REQUIRED 表示在标记中必须出现此属性。 #IMPLIED 标记中可以不出现此属性。即该属性不是必须使用。 #FIXED 属性的值是固定的某个值。 字符串 标记中如没有指定属性的值,那么此字符串就是此属性的值。 示例: ①属性值为字符数据,默认值为numeric,在未指定其他值时使用该值。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format CDATA “numeric”> ②属性有一默认值numeric,并且必须使用该值作为属性的值。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format CDATA #FIXED “numeric”> ③属性无默认值,但它必须出现在year元素中。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format CDATA #REQUIRED> ④属性值为numeric或character,而numeric为默认值。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format (numeric|character) ”numeric”> ⑤属性值为numeric或character,在此处numeric被固定为唯一的实际值。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format (numeric|character) #FIXED”numeric”> ⑥属性必须有一个值,numeric或character。 <!ELEMENT year (#PCDATA)> <!ATTLIST year format (numeric|character) #REQUIRED > 4.DOCTYPE声明 DTD可以是一个完全独立的文件,也可以在XML文件中直接设定。所以,DTD分为外部DTD(在XML文件中调用另外已经编辑好的DTD)和内部DTD(在XML文件中直接设定 DTD)两种。 4.1内部DOCTYPE声明 如果DTD被包含在XML源文件中,它将通过以下语法格式来在"DOCTYPE"中定义: <!DOCTYPE root-element [element-declarations]> 示例: <?xml version="1.0"?> <!DOCTYPE note [ <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend</body> </note> 其中,<!DOCTYPE note (在第2行) 定义这是一个类型为note的文档。此名(note)必须与XML文档的根元素名相同。 4.2外部DOCTYPE声明 如果DTD在XML源文件的外部,它将通过以下语法格式来在"DOCTYPE"中定义: <!DOCTYPE root-element SYSTEM "filename"> 示例:此例XML文档与例1相同,但是使用的是外部的DTD <?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note> 文件note.dtd包含定义的DTD <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> 关键字SYSTEM表示外部DTD是个人的非标准化的DTD,这与PUBLIC不同,它表示该DTD是一个公用的DTD。格式如下: <!DOCTYPE note PUBLIC “-//Big Dog//DTDsustomer_support//EN//” “http://www.bigdog.net/xml/customer.dtd”> 名称的各个部分是: ①名称以加号或减号开头。加号表示该DTD已经通过标准组织的批准。减号表示该DTD未经标准化。 ②//Big Dog//DTD表示编写和维护该DTD的个人或组织。 ③sustomer_support是对此DTD的描述,//EN//表示该DTD所用的语言,是英语。 5.实体 实体是用于定义普通文本快捷方式的变量。实体参数就是反映实体特征的参数。实体可以声明为内部实体或外部实体。 5.1内部实体声明 Syntax: <!ENTITY entity-name "entity-value"> DTD Example: <!ENTITY writer "Donald Duck."> <!ENTITY copyright "Copyright W3Schools."> XML example: <author>&writer;©right;</author> 5.2外部实体声明 Syntax: <!ENTITY entity-name SYSTEM "URI/URL"> DTD Example: <!ENTITY writer SYSTEM "http://www.w3schools.com.sixxs.org/dtd/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.w3schools.com.sixxs.org/dtd/entities.dtd"> XML example: <author>&writer;©right;</author> 5.3 在实体中使用标记字符的限制 限制1:任何标记字符必须被双重定义。考虑下面的例子: <!ENTITY name”black&white”> XML example: <text>This is not a &name;choice.</text> 希望此实体用“This is not a black &white choice”来替换“&name;”。现在考虑实际上所发生的如下过程。 ①XML处理器看到实体引用&name;并寻找替换文本。 ②找到“black&white”,并替换为“black &white”。 ③XML处理器插入替换文本,结果代码是: <text>This is not a black & white choice.</text> ④处理器试图分析“&”,结果报告一个错误,因为“&”未被声明为一个实体。 解决方法是:使用标记字符的双重转义,这将会避免此问题的发生,例如: <!ELEMENT name”Harry&#38;Fred&amp;Joe”> XML example: <text>The job was left to &name; to fix.</text> 希望此实体用“The job was left to Harry&Fred&Joe”来替代“&name;”。现在考虑实际上所发生的如下过程。 ①XML处理器看到实体引用&name;并寻找替换文本。 ②找到“Harry&#38;Fred&amp;Joe”,并替换为“Harry&Fred&Joe”。 ③XML处理器插入替换文本,结果代码是: <text>The job was left to Harry&Fred&#amp;Joe.</text> ④然后处理器顺利的分析“&”和“&#amp;”,得到: <text> The job was left to Harry&Fred&Joe</text> 限制2:如果在替换文本中打开某一元素而不关闭它是错误的。考虑下面的例子: <!ELEMENT unsafe”&#60;emph>Harry and Joe”> XML example: <text>The job was left to &unsafe;to finish.</text> 结果是: <text>The job was left to <emph>to finish.</text>//这是非法的。 5.4 参数实体 DTD Example: <?xml version=”1.0” standalone=”no”?> <!DOCTYPE message[ <!ELEMENT message(header,body,(signature|footer))> <!ELEMENT header(date,form+,to+,subject,banner?)> <!ELEMENT body (paragraph*)> <!ATTLIST body studentid IDREFS #REQUIRED> <!ELEMENT paragraph(#PCDATA)> <!ATTLIST paragraph size NMTOKENS #REQUIRED> <!ELEMENT signature(#PCDATA)> <!ELEMENT footer ANY> <!ATTLIST footer studentwhich IDREF #REQUIRED> <!ELEMENT from(#PCDATA)> <!ATTLIST from student ID #REQIIRED> <!ELEMENT to(#PCDATA)> <!ATTLIST to relationship CDATA #IMPLIED> <!ELEMENT subject(#PCDATA)> <!ELEMENT banner(#PCDATA)> <!ENTITY % date SYSTEM “message.ent”> %date; ]> XML example: <message> <header> <date> <day>25</day> <month type=”character”>December</month> <year format=”numeric”>2010</year> </date> <from student=”a123”>Me</from> <from student=”a456”>My friend</from> <to>You</to> <to relationship=”very close”>Your family</to> <to relationship=”not so close”>Your friends</to> <subject>Happy New Year</subject> <banner></banner> </header> <body> <paragraph size=”one line”>Best wishes</paragraph> <paragraph size=”two lines”>Hope</paragraph> </body> <footer> <day>A new day</day> <from student=”a3344”>Stalle’s helper</from> </footer> </message> 其中,date元素及其子元素的定义被放在一个单独的文件中,文件名为message.ent,内容为: <!ELEMENT date(day,month,year)> <!ELEMENT day(#PCDATA)> <!ELEMENT month(#PCDATA)> <!ATTLIST month type(numeric|character)#REQUIRED> <!ELEMENT year(#PCDATA)> <!ATTLIST year format(numeric|character)”numeric”> DTD中的下面两行代码使得上面的代码片断在分析时被包含到DTD中。 <!ENTITY % date SYSTEM “message.ent”> %date; 第一行用于引用文件message.ent中date的元素定义。符号”%”两边的空格是必须的。第二行以正常形式使用一个实体饮用,使它被文件的内容所替代。
?