跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

技巧: 何时使用局部声明和全局声明

XML Schema 中的两类元素

Author photo
Benoit Marchal 是一位比利时籍的顾问。他是 XML by Example 和其它几本 XML 图书的作者。Benoit 可以为您的 XML 项目提供帮助。可以通过 bmarchal@pineapplesoft.com 或者他的个人网站 marchal.com 与他联系。

简介: W3C XML Schema 提供了许多用于构建和组织 XML 词汇表的功能强大的选项。在本技巧中,Benoit 比较了元素的全局声明和局部声明,并提供了什么时候该使用何种声明的提示。

发布日期: 2003 年 3 月 01 日
级别: 中级
访问情况 : 1317 次浏览
评论: 


由于 XML 开发人员需要克服 DTD 作为建模语言的限制,所以 W3C XML Schema 变得越来越流行了。XML Schema 的特别流行是由于它提供了更丰富的数据类型。使用 XML Schema,可以很容易地指定一个元素应该包含文本、数字、布尔值还是其他一些数据类型。

不过,XML Schema 提供了比数据类型更多的功能。它具有组织元素声明的选项,可以改进可读性和易维护性。在本技巧中,我将为您展示XML Schema 中的范围选项。

局部声明与全局声明

XML Schema 让您可以直接在 xs:schema 元素下面声明元素,或者作为另一个声明的一部分声明元素。直接出现在 xs:schema 元素下面的声明具有 全局范围,而其他声明具有 局部范围。全局声明并不是新东西 -- DTD 中就已经引入它们了 -- 但是局部声明是 XML Schema 所独有的。

元素的全局声明和局部声明最明显的区别是在其他声明中可以引用全局声明,而局部声明只能存在于它们自己的局部范围内。一个实际的副作用是全局声明必须是唯一的:任何两个全局声明都不能有相同的元素名。另一方面,局部声明如果是在不同的上下文中,则不会产生冲突。甚至可以在局部覆盖一个全局声明。

为什么想要覆盖声明呢?在设计大型模式、特别是设计从现有模式中导入声明的新模式时,这是很有用的。在后一种情况下,导入的模式确实可能具有会引起冲突的声明。

例如 ,一个模式可能定义一个 key 元素为用于密钥的 base64 数据,而另一个模式将 key 定义为一个用于储存数据库标识符的整数。在这里, key 元素有两个不同的定义,如果要创建所导入的前两者的第三个模式就会产生问题。


分析例子

清单 1中的 模式 全部使用全局声明。 <xs:element name="..."> construct 定义了一个新元素,它类似于 DTD 中的 <!ELEMENT ...> 语句。这些声明可能会通过 <xs:element ref="..."/> construct 引用其他声明。


清单 1. 全局声明
<?xml version="1.0"?>
<xs:schema targetNamespace="http://ananas.org/2003/tips/local"
           xmlns:tp="http://ananas.org/2003/tips/local"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
   <xs:complexType>
      <xs:sequence>
         <xs:element 
        ref="tp:movie" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>
</xs:element>
<xs:element name="movie">
   <xs:complexType>
      <xs:sequence>
         <xs:element 
        ref="tp:title"/>
         <xs:element 
        ref="tp:genre" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>
</xs:element>
<xs:element name="title" type="xs:string"/>
<xs:element name="genre" type="xs:string"/>
</xs:schema>
      

引用和名称空间

引用一个全局元素定义时,需要提供完全限定的名字,包括相应的名称空间前缀(如 ref="tp:title" )。不过,元素声明是一个非限定名( name="title" )。这种行为背后的逻辑(有些扭曲)是:模式中的每一个声明都自动进入目标名称空间。是的,这有些让人迷惑,但是至少警告过您了。

另一方面,清单 2尽可能地使用了局部声明。唯一的全局声明是用于文档的根的(文档的根必须是全局声明,因为根没有父元素)。所有其他声明都嵌入到根声明下面。大量的嵌套使这种方法得到了一个别名“俄罗斯娃娃”。


清单 2. 局部声明
<?xml version="1.0"?>
<xs:schema targetNamespace="http://ananas.org/2003/tips/local"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
<xs:element name="list">
   <xs:complexType>
      <xs:sequence>
         
        <xs:element name="movie" maxOccurs="unbounded">
            <xs:complexType>
               <xs:sequence>
                  
        <xs:element name="title" type="xs:string"/>
                    <xs:element name="genre" maxOccurs="unbounded" 
                        type="xs:string"/>
               </xs:sequence>
            </xs:complexType>
         </xs:element>
      </xs:sequence>
   </xs:complexType>
</xs:element>
</xs:schema>
      

注意 elementFormDefault 属性的使用。在默认情况下,XML 文档中具有局部声明的元素是非限定的(它们没有名称空间前缀)。背后的推论是非限定的元素类似于属性,因为属性在默认情况下是非限定的。

清单3展示了非限定的局部元素。在这里, movietitle genre 元素没有名称空间前缀,假定它们与其父元素在同一个名称空间中。对于非限定的局部元素的使用尚无定论。SOAP 成功地使用了一些,但是大多数用户认为它们是让人困惑的。

一句警告:需要将 清单 2中的 elementFormDefaultqualified 改为 unqualified 以验证清单 3。


清单 3. 非限定的局部元素

<?xml version="1.0"?> <tp:list xmlns:tp="http://ananas.org/2003/tips/local"> <movie>
<title>Johnny English </title>
<genre>comedy </genre>
</movie>
<movie>
<title>Finding Nemo </title>
<genre>family </genre>
</movie> </tp:list>

显然,如果要在文档中使用非限定的元素,那么必须使用局部元素。


得出结论

那么,局部声明和全局声明哪一个更好呢? 唉,就像设计策略的常见情况一样,答案不是这么黑白分明的,大多数模式同时使用两者。局部声明之所以有意义是因为它们隔离了模式的一部分。局部名对于其他上下文是不透明的,这使命名冲突的风险降到了最低。

局部声明的另一项好处是它们明确地标识了文档中可能的根。

局部声明的主要缺点是它们不能重复使用。在 清单 2中(使用局部声明),不能在另一个上下文中重复使用 movie 元素。在 清单 1中(使用全局声明)这是很容易的。

结论是,哪一种选择是最好的取决于元素的本性:一个准备在模式中别的地方重复使用的自包含元素最好使用全局声明,而只在给定上下文中起作用的元素应该在局部声明。

假定 movie 是一个自包含的元素,那么清单 4是一种更好的模式,它很好地结合了局部和全局声明。


清单 4. 混合声明

<?xml version="1.0"?> <xs:schema targetNamespace="http://ananas.org/2003/tips/local" xmlns:tp="http://ananas.org/2003/tips/local" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="list"> <xs:complexType> <xs:sequence> <xs:element ref="tp:movie" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="movie"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="genre" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

尽管在本技巧中没有讨论,但是您还可以在全局和本地声明中使用类型定义以改进模式的可读性。


参考资料

关于作者

Author photo

Benoit Marchal 是一位比利时籍的顾问。他是 XML by Example 和其它几本 XML 图书的作者。Benoit 可以为您的 XML 项目提供帮助。可以通过 bmarchal@pineapplesoft.com 或者他的个人网站 marchal.com 与他联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=21665
ArticleTitle=技巧: 何时使用局部声明和全局声明
publish-date=03012003
author1-email=bmarchal@pineapplesoft.com
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。