以文本方式查看主题 - 中文XML论坛 - 专业的XML技术讨论区 (http://bbs.xml.org.cn/index.asp) -- 『 DTD/XML Schema 』 (http://bbs.xml.org.cn/list.asp?boardid=23) ---- 元素声明(一) (http://bbs.xml.org.cn/dispbbs.asp?boardid=23&rootid=&id=8362) |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:40:00 AM -- 元素声明(一) 在合法的XML文档中使用的每项标记都要在DTD中的元素声明中加以声明。一项元素声明指明了元素名称和元素可能的内容。内容清单有时称为内容规格。内容规格使用一种简单的语法精确地指明文档中允许什么和不允许什么。这听起来复杂,却只需在元素名称上加上如*、?或+的标点以便指明它可能出现不止一次,可能出现或可能不出现,或必须出现至少一次。 DTD很保守,没有明确允许的就是禁止的。然而,DTD句法使您能够严格地区分那些用语句很难说清的关系。例如,DTD很容易地说明GIVEN_NAME要在SURNAME前,而SURNAME必须放在POSITION前,POSITION要放在GAME前,GAME要放在GAMES_STARTED前,GAMES_STARTED要放在AT_BATS前,AT_BATS要放在RUNS前,RUNS要在HITS前,所有这些只能出现在一个PLAYER元素内。 从外到内,逐级建立DTD是最容易的。这使您能在建立DTD的同时建立一份样本文档来验证DTD本身是合法的和真正地描述您想要的格式。 1 ANY 要做的第一件事是标识基本元素。在棒球的例子中,SEASON是基本元素。!DOCTYPE声明指明了这一点: 所有的元素类型声明都以<!ELEMENT(区分大小写)开头而以>结束。其中包括声明的元素名称(本例中为SEASON)后接内容规格。关键词ANY(也要区分大小写)表明所有可能的元素以及可析的字符数据都可以是SEASON元素的子元素。 基本元素使用ANY是通常的作法--尤其是对未结构化的文档--但对多数其他元素则应避免使用ANY。通常每项标记的内容应尽可能准确。DTD 经常是在整个开发过程中逐步完善的,随着反映应用情况和首制作中未预料的情况,严格性将减少。所以,最好是开始时严格,以后再放松些。 |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:42:00 AM -- 元素声明(二) 2 #PCDATA 尽管文档中可以出现任何元素,但出现的元素必须声明。第一个需要声明的元素是YEAR,下面是YEAR元素的元素声明: 以下这些YEAR元素都是合法的: 甚至下面这个YEAR元素也是合法的,因为XML不会去检查PCDATA的内容,只要是不包括标记的文本就可以。 SEASON和YEAR元素声明应包括在文档类型声明中,如下所示: 通常,空格和缩进无关紧要。元素声明的顺序也不重要。下面这一文档类型声明的作用与上面的声明相同: 上面两个文档声明都是说一个SEASON元素可以包含可析的字符数据和以任意顺序声明的任意数量的其他元素。本例中如此声明的元素只有YEAR,它只能包含可析的字符数据。例如考虑清单1中的文档。 因为SEASON元素也可以包含可析的字符数据,所以可以在YEAR元素之外附加文本,如清单2所示。 我们最后是不接受这样的文档的。但是此时它是合法的,因为SEASON被声明为可以接受ANY内容。大多数时候,在定义一个元素的所有子元素之前以ANY代替一个元素,就比较容易起步。然后再用实际的子元素来替换ANY。 清单3:包含样式单、一个YEAR元素和正常文本的合法文档 |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:43:00 AM -- 元素声明(三) 3 子元素列表 由于SEASON元素被声明为可以接受任何元素作为子元素,因而可以接受各种各样的元素。当遇到那些多多少少有些非结构化的文本,如杂志文章时,这种情况就很有用。这时段落、副栏、项目列表、序号列表、图形、照片以及子标题可出现在文档的任意位置。然而,有时可能想对数据的安排上多实行些规则和控制。例如,可能会要求每一个LEAGUE元素有一个LEAGUE_NAME子元素,而每个PLAYER元素要有一个GIVEN_NAME和SURNAME子元素,并且GIVEN_NAME要放在SURNAME之前。 为了声明LEAGUE元素必须有一个名称,只要声明LEAGUE_NAME元素,然后在LEAGUE声明后的括号内加入LEAGUE_NAME,如下面这样: 每个元素只能在其<!ELEMENT>内声明一次,即使它以其他<!ELEMENT>声明的子元素出现也一样。这里,我把LEAGUE_NAME声明放在引用它的LEAGUE声明之后,这没有关系。XML允许这一类提前引用。只要声明全部包含在DTD中,元素标记出现的顺序无关紧要。 清单4:有两个LEAGUE子元素的SEASON元素 让我们限制一下SEASON元素。一个SEASON元素包含正好一个YEAR元素和其后的两个LEAGUE子元素。不把SEASON元素声明为可以包含ANY元素,我们在SEASON元素声明中包括这三个子元素,用括号括起来并用逗号分隔开,如下所示: 清单4所列的文档部分确实符合这项DTD的规定,因为它的SEASON元素包含一个YEAR子元素,后接两个LEAGUE子元素,再没有别的。但是,如果文档只包括一个SEASON元素,那么这个文档尽管结构完整,也将是非法的。同样,如果LEAGUE在YEAR之前而不是在其后,或者如果LEAGUE有YEAR子元素,或者文档在其他任何方面不符合DTD,那么文档就是不合法的,合法性检查程序将拒绝这样的文档。 可直接将此种技术推广到DIVISION元素。每个LEAGUE有一个LEAGUE_NAME和三个DIVISION子元素。例如: 5 一个或多个子元素 每个DIVISION有一个DIVISION_NAME和四到六个TEAM子元素。指定DIVISION_NAME很容易,方法如下: |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:44:00 AM -- 元素声明(四) 6 零或多个子元素 每个TEAM要包含一个TEAM_CITY,一个TEAM_NAME和不确定数目的PLAYER元素。实际上,棒球队至少要九名球员。但是,本书的很多例子中由于篇幅的原因而没有列出球员。因而,我们要指明一个TEAM元素可包含零或多个PLAYER子元素。在子元素清单中在元素名上附加一个星号(*)来实现这一目的。例如: 7 零或一个子元素 文档中出现的最后的元素是PLAYER子元素。它们全部是只包含文本的简单元素。下面是它们的声明: 现在我们可以编写PLAYER的元素声明了。所有球员有一个GIVEN_NAME、一个SURNAME、一个POSITION、一个GAMES。我们可声明每个PLAYER元素有一个AT_BATS、RUNS、HITS等等。但是,对于没有击球的投球手列出零得分是否准确还不敢确定。因为这可能出现这样一种情况,就是在开始计算平均击球数等问题时会导致被零除的错误。如果某一特定的元素不适合于给定的球员,或没有这一元素,那么就应该从该球员信息中忽略这一元素的统计。对于给定的球员我们不允许多于一个这样的元素。因而,我们就需要给定类型的零个或一个元素。在子元素列表后面附加一个问号(?)可表明这一点,如下所示: 这就是说每个PLAYER元素有一个GIVEN_NAME、SURNAME、POSITION、GAMES和GAMES_STARTED子元素。而且,每名球员可能有或可能没有AT_BATS、RUNS、HITS、DOUBLES、TRIPLES、HOME_RUNS、RBI、STEALS、CAUGHT_STEALING、SACRIFICE_HITS、SACRIFICE_FLIES、ERRORS、WALKS、STRUCK_OUT和HIT_BY_PITCH。 |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:45:00 AM -- 元素声明(五) 8 完整的文档和DTD 我们现在有了棒球统计的完整的DTD。这一DTD连同清单8-4中的文档部分一起,列在清单8-9中。 |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:46:00 AM -- 元素声明(六) 8 完整的文档和DTD(续前页) 清单8-10:另外一份符合棒球DTD的合法的XML文档 <?xml version="1.0" standalone="yes"?> <!DOCTYPE SEASON [ <!ELEMENT YEAR (#PCDATA)> <!ELEMENT LEAGUE (LEAGUE_NAME, DIVISION, DIVISION, DIVISION)> <!ELEMENT LEAGUE_NAME (#PCDATA)> <!ELEMENT DIVISION_NAME (#PCDATA)> <!ELEMENT DIVISION (DIVISION_NAME, TEAM+)> <!ELEMENT SEASON (YEAR, LEAGUE, LEAGUE)> <!ELEMENT TEAM (TEAM_CITY, TEAM_NAME, PLAYER*)> <!ELEMENT TEAM_CITY (#PCDATA)> <!ELEMENT TEAM_NAME (#PCDATA)> <!ELEMENT PLAYER (GIVEN_NAME, SURNAME, POSITION, GAMES, GAMES_STARTED, COMPLETE_GAMES?, WINS?, LOSSES?, SAVES?, AT_BATS?, RUNS?, HITS?, DOUBLES?, TRIPLES?, HOME_RUNS?, RBI?, STEALS?, CAUGHT_STEALING?, SACRIFICE_ HITS?, SACRIFICE_FLIES?, ERRORS?, WALKS?, STRUCK_OUT?, HIT_BY_PITCH?, COMPLETE_GAMES?, SHUT_OUTS?, ERA?, INNINGS?, EARNED_RUNS?, HIT_BATTER?, WILD_PITCHES?, BALK?, WALKED_BATTER?, STRUCK_OUT_BATTER?) > <!ELEMENT SURNAME (#PCDATA)> <!ELEMENT GIVEN_NAME (#PCDATA)> <!ELEMENT POSITION (#PCDATA)> <!ELEMENT GAMES (#PCDATA)> <!ELEMENT GAMES_STARTED (#PCDATA)> <!ELEMENT COMPLETE_GAMES (#PCDATA)> <!ELEMENT WINS (#PCDATA)> <!ELEMENT LOSSES (#PCDATA)> <!ELEMENT SAVES (#PCDATA)> <!ELEMENT AT_BATS (#PCDATA)> <!ELEMENT RUNS (#PCDATA)> <!ELEMENT HITS (#PCDATA)> <!ELEMENT DOUBLES (#PCDATA)> <!ELEMENT TRIPLES (#PCDATA)> <!ELEMENT HOME_RUNS (#PCDATA)> <!ELEMENT RBI (#PCDATA)> <!ELEMENT STEALS (#PCDATA)> <!ELEMENT CAUGHT_STEALING (#PCDATA)> <!ELEMENT SACRIFICE_ HITS (#PCDATA)> <!ELEMENT SACRIFICE_FLIES (#PCDATA)> <!ELEMENT ERRORS (#PCDATA)> <!ELEMENT WALKS (#PCDATA)> <!ELEMENT STRUCK_OUT (#PCDATA)> <!ELEMENT HIT_BY_PITCH (#PCDATA)> <!ELEMENT SHUT_OUTS (#PCDATA)> <!ELEMENT ERA (#PCDATA)> <!ELEMENT INNINGS (#PCDATA)> <!ELEMENT HOME_RUNS_AGAINST (#PCDATA)> <!ELEMENT RUNS_AGAINST (#PCDATA)> <!ELEMENT EARNED_RUNS (#PCDATA)> <!ELEMENT HIT_BATTER (#PCDATA)> <!ELEMENT WILD_PITCHES (#PCDATA)> <!ELEMENT BALK (#PCDATA)> <!ELEMENT WALKED_BATTER (#PCDATA)> <!ELEMENT STRUCK_OUT_BATTER (#PCDATA)> ]> <SEASON> <YEAR>1998</YEAR> <LEAGUE><LEAGUE_NAME>National</LEAGUE_NAME> <DIVISION> <DIVISION_NAME>East</DIVISION_NAME> <TEAM> <TEAM_CITY>Atlanta</TEAM_CITY> <TEAM_NAME>Braves</TEAM_NAME> </TEAM> <TEAM> <TEAM_CITY>Florida</TEAM_CITY> <TEAM_NAME>Marlins</TEAM_NAME> </TEAM> <TEAM> <TEAM_CITY>Montreal</TEAM_CITY> <TEAM_NAME>Expos</TEAM_NAME> </TEAM> <TEAM> <TEAM_CITY>New York</TEAM_CITY> <TEAM_NAME>Mets</TEAM_NAME> </TEAM> <TEAM> <TEAM_CITY>Philadelphia</TEAM_CITY> <TEAM_NAME>Phillies</TEAM_NAME> </TEAM> </DIVISION> <DIVISION> <DIVISION_NAME>Central</DIVISION_NAME> <TEAM> <TEAM_CITY>Chicago</TEAM_CITY> <TEAM_NAME>Cubs</TEAM_NAME> </TEAM> </DIVISION> <DIVISION> <DIVISION_NAME>West</DIVISION_NAME> <TEAM> <TEAM_CITY>Arizona</TEAM_CITY> <TEAM_NAME>Diamondbacks</TEAM_NAME> </TEAM> </DIVISION> </LEAGUE> <LEAGUE> <LEAGUE_NAME>American</LEAGUE_NAME> <DIVISION> <DIVISION_NAME>East </DIVISION_NAME> <TEAM> <TEAM_CITY>Baltimore</TEAM_CITY> <TEAM_NAME>Orioles</TEAM_NAME> </TEAM> </DIVISION> <DIVISION> <DIVISION_NAME>Central</DIVISION_NAME> <TEAM> <TEAM_CITY>Chicago</TEAM_CITY> <TEAM_NAME>White Sox</TEAM_NAME> </TEAM> </DIVISION> <DIVISION> <DIVISION_NAME>West</DIVISION_NAME> <TEAM> <TEAM_CITY>Anaheim</TEAM_CITY> <TEAM_NAME>Angels</TEAM_NAME> </TEAM> </DIVISION> </LEAGUE> </SEASON> |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:47:00 AM -- 元素声明(七) 9 选择 通常,一个父元素会有许多子元素。为了指明各子元素必须按顺序出现,可将这些子元素用逗号隔开。每个这样的子元素还可以以问号、加号或星号作后缀,以便调节它在那一位置按顺序出现的次数。 到目前为止,已经假定子元素以一定的顺序出现或不出现。还可以使DTD更加灵活,如允许文档作者在给定的地方选择不同的元素。例如,在一项描述顾客购物的DTD中,结帐方式信息中的每项PAYMENT元素都有CREDIT_CARD子元素或CASH子元素以便提供付款方式的信息。然而,单独的PAYMENT元素不能同时使用两者。 在父元素声明中,可以使用竖线(1)而不是逗号来分开子元素,以便指明文档作者需要输入一个或另一个子元素。例如,下面的语句就说明PAYMENT元素必须有CASH或CREDIT_CARD中的一个子元素。 |
-- 作者:npuhetao -- 发布时间:6/19/2004 10:49:00 AM -- 呵呵,贴了这么多,希望对大家有所帮助! |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
93.750ms |