zoukankan      html  css  js  c++  java
  • XML 模式:了解结构

    XML 模式:了解结构

    了解如何使用 XML 模式结构声明、扩展和限制 XML 的结构。

    本系列中的其他文章:
    XML 模式:了解命名空间
    XML 模式:了解数据类型

    语法定义语言的结构和语义、实施约束以及确保实例(实际数据)的有效性。正如英语(或任何其他语言)具有关联的语法来定义有关特殊句子的撰写规则,或者在给定英语句子的情况下,利用语法来检查该句的有效性一样,XML 实例文档的语法也定义相应的规则以确保该文档的结构和内容的有效性。

    W3C XML 模式定义 (WXS) 采用 XML 语言表示 W3C XML 模式 (WXS) 的抽象数据模型。通过定义模式的抽象数据模型,W3C 模式并不知道用于表示该模型的语言。XML 表示形式是 WXS 指定的正式表示形式,但您可以根据所需的任何方式表示抽象数据模型并将它用于验证。例如,您可以使用任何符合抽象数据模型的数据结构直接创建内存中的模式。这将促使开发 W3C 模式验证程序的供应商提供一个可用于直接创建内存中模式的 API。

    验证 XML 实例文档的语法有多种。某些语法很快便过时,而其他语法(如 DTD,它是 W3C XML 1.0 REC 的一部分)则已经通过了时间的考验。在现有语法中,XML 模式在 XML 开发人员中应用最广,这是因为:

    1. 它使用 XML 语言来定义模式。
    2. 它具有 44 个以上的内置数据类型,可以对其中的每一个数据类型进行进一步地优化,以对 XML 中的字符数据进行细粒度验证。
    3. 可以使用 minOccurs 和 maxOccurs 属性以细粒度方式定义元素的基数。
    4. 它通过 extension、restriction、import、include 和 redefine 结构支持模块化和可重用性。
    5. 它支持标识约束,以确保 XML 文档中的值在指定集中的唯一性。
    6. 它具有抽象数据模型,因此它的表示形式并不限于 XML。

    以下是一个有关如何根据外部指定的模式来验证 XML 实例的示例:

    import java.io.FileInputStream;
    import oracle.xml.parser.v2.XMLError;
    import oracle.xml.parser.schema.XML Schema;
    import oracle.xml.parser.schema.XSDBuilder;
    import oracle.xml.schemavalidator.XSDValidator;
    ...
    //加载 XML 模式
    XSDBuilder schemaBuilder = new XSDBuilder();
    XML Schema schema = schemaBuilder.build(new FileInputStream("myschema.xsd"), null);
    
    //将加载的 XML 模式设置为 XSDValidator
    XSDValidator validator = new XSDValidator();
    validator.setSchema(schema);
    
    //针对提供的 XML 模式验证 XML 实例。
    validator.validate(new FileInputStream("data.xml"));
    
    //检查错误
    XMLError error = validator.getError();
    if (error.getNumMessages() > 0) {
    System.out.println("XML-instance is invalid.");
    error.flushErrors();
    }
    else {
    System.out.println("XML-instance is valid.");
    }
    

    当然,XML 模式也有限制:

    1. 它不支持基于规则的验证。一个基于规则的验证示例为:如果属性“score”的值大于 80,则 XML 实例中必须存在元素“distinction”,否则元素不存在。
    2. 唯一粒子属性 (UPA) 约束过分严格地定义了用于所有类型的 XML 文档的语法。(有关更多信息,请参阅“UPA 约束”。)

    在我的前几篇文章中,我介绍了命名空间的概念(在您深入研究 XML 模式之前必须了解它)、XML 模式中支持的数据类型以及用于进一步限制和使用这些数据类型的 simpleType 结构。

    在本文中,我将介绍用于声明、扩展和限制 XML 结构的模式。您还将学习由 XML 模式提供的模型组、粒子以及其他约束。

    Oracle XML 开发人员工具包 (XDK) 包含一个符合 W3C 标准的 XML 模式处理器以及多个实用工具,如利用 API 通过编程来创建并限制模式数据类型、分析和验证 XML 模式结构本身以及遍历 XML 模式的抽象数据模型的实用工具。请检查 oracle.xml.parser.schema 和 oracle.xml.schemavalidator 程序包。

    内容和模型

    元素内容

    在 XML 文档中,元素内容是指包含在它的 <头> 和 </尾> 标记之间的内容。元素只能有四种类型的内容:TextOnly(纯文本)、ElementOnly(纯元素)、Mixed(混合)和 Empty(空)。在元素上声明的属性并视为是元素内容的一部分。它们只是其声明所在的元素的一部分,他们组成了 XML 的结构。

    TextOnly

    如果元素在其 <头> 和 </尾> 标记之间只有字符数据(或简单称为文本数据),即如果元素没有子元素,则该元素的内容被视为是 TextOnly(纯文本)。例如:

    <TextOnly>some character data</TextOnly>
    

    ElementOnly

    如果元素在其 <opening> 和 </closing> 标记之间只有子元素(可以选择性地由空格、制表符、换行符、回车符分隔),则该元素的内容被视为是 TextOnly(纯元素)。这些空格被称作是可忽略的空格,并通常用于对 XML 进行缩进。因此,以下内容:

    没有空格的 ElementOnly 内容

    <ElementOnly><child1 .../><child2 .../></ElementOnly>
    

    等价于:

    空格的 ElementOnly 内容

    <ElementOnly>
    <child1 .../>
    <child2 .../>
    </ElementOnly>
    

    混合

    如果元素的字符数据与子元素分散在 <头> 和 </尾巴> 标记之间,则该元素的内容被视为是 Mixed(混合)。(换言之,它的内容同时包含字符数据和子元素。)混合内容后,前面所说的可忽略空格将不再是可忽略的。因此,以下内容:

    <Mixed><child1.../>some character data<child1.../></Mixed>
    

    不同于:

    <Mixed>
    <child1 .../>
    some character data
    <child1 .../>
    </Mixed>
    

    如果元素在 <头> 和 </尾> 标记之间绝对没有任何内容(甚至是空格),则该元素的内容被视为是 Empty(空)。例如:

    <Empty></Empty>
    

    另一种便于使用,并且格式清晰的元素(具有空内容)表示方法是使用单个 Empty 标记,如下所示:

    <Empty />
    

    内容模型

    在 XML 语法中,您可以声明元素的内容模型,以指定相应 XML 实例文档中的元素内容类型。因此,内容模型是元素内容的定义。

    下图演示了如何在 XML 模式中声明内容模型。沿着图中从 <schema> 开始的路径深入探讨,以了解如何声明四种元素内容(包含和不包含属性声明)的内容模型。让我们简单介绍一下每个元素内容。

    图 1
    图 1:在 XML 模式中声明内容模型

    TextOnly

    在以上图示中,沿路径找到 simpleType-1 以使用 TextOnly 内容模型声明元素:

    <xsd:element name="TextOnly">
    <xsd:simpleType>
    <xsd:restriction base="xsd:string" />
    </xsd:simpleType>  
    </xsd:element>
    
    或等价于
    
    <xsd:element name="TextOnly" type="xsd:string" />
    

    以上模式使用 TextOnly 内容模型声明了一个名为“TextOnly”(可以为任何名称)的元素,其内容必须是相应 XML 实例中的整数。如果元素的内容模型为 TextOnly,则它始终有一个关联的 simpleType,用于指示该元素的数据类型。例如,在本示例中,元素 TextOnly 的数据类型为 string。请参阅上一部分中此模式的相应 XML 实例。

    正如前面指出的,属性并不是元素内容;因此,另一个具有 TextOnly 内容并具有属性的 XML 实例的示例为:

    <TextOnly att="val">some character data</TextOnly>
    

    现在,沿着图 1 中的路径找到 simpleContent-3,以使用 TextOnly 内容模型和属性声明一个元素:

    <xsd:element name="TextOnly">
    <xsd:complexType>
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="att" type="xsd:string" use="required" />
    </xsd:extension>
    </xsd:simpleContent>
    </xsd:complexType>
    </xsd:element>
    

    以上模式使用 TextOnly 内容模型声明一个名为“TextOnly”的元素,其内容必须为字符串并且在相应的 XML 实例中必须有一个名为“attr”的属性。

    ElementOnly

    沿着图 1 中的路径直到找到 sequence-5、choice-6 之一或 all-7,以使用 ElementOnly 内容模型声明一个元素:

    <xsd:element name="ElementOnly">
    <xsd:complexType>
    <xsd:sequence> <!-- could have used choice or all instead —>
    <xsd:element name="child1" type="xsd:string" />
    <xsd:element name="child2" type="xsd:string" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    

    以上模式使用 ElementOnly 内容模型声明一个名为“ElementOnly”的元素。元素“ElementOnly”在相应的 XML 实例文档中必须具有子元素“child1”和“child2”。请参阅上一部分中此模式的相应 XML 实例。

    另一个包含 ElementOnly 元素内容和属性的 XML 实例如下所示:

    <ElementOnly att="val">
    <child1 .../>
    <child2 .../>
    </ElementOnly>
    

    要使用 ElementOnly 内容模型和属性声明一个元素,图 1 中的路径与声明 ElementOnly 内容模型的路径相同。然后,按如下所示在 complexType 中声明属性:

    <xsd:element name="ElementOnly">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" />
    <xsd:element name="child2" type="xsd:string" />
    </xsd:sequence>
    <xsd:attribute name="att" type="xsd:string" use="required" />
    </xsd:complexType>
    </xsd:element>
    

    以上模式的相应 XML 实例如下

    <Mixed att="val">
    <child1 .../>
    some character data
    <child1 .../>
    </Mixed>
    

    混合型

    没着图 1 中的路径找到 sequence-5、choice-6 之一或 all-7,以使用 Mixed 内容模型(它与声明 ElementOnly 内容模型相同)声明元素,但这次将 complexType 的 mixed 属性设置为 true,如下所示:

    <xsd:element name="Mixed">
    <xsd:complexType mixed="true">
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" />
    <xsd:element name="child2" type="xsd:string" />
    </xsd:sequence>
    <xsd:attribute name="att" type="xsd:string" use="required" />
    </xsd:complexType>
    </xsd:element>
    

    Empty

    沿着此路径直到找到 complexType-2 以使用 Empty 声明一个具有或没有属性的元素:

    <xsd:element name="EmptyContentModels">
    <xsd:complexType>
    <xsd:sequence>
    
    <xsd:element name="Empty1">
    <xsd:complexType />
    </xsd:element>
    
    <xsd:element name="Empty2">
    <xsd:complexType>
    <xsd:attribute name="att" type="xsd:string" use="required" />
    </xsd:complexType>
    </xsd:element>
    
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    

    以上模式的相应 XML 实例如下

    <EmptyContentModels>
    <Empty1 />
    <Empty2 att="val" />
    </EmptyContentModels>
    

    模型组

    如果将元素的内容模型声明为 ElementOnly或混合型(意味着该元素具有子元素),则可以使用模型组更详细地指定子元素的顺序出现位置。模型组由粒子组成;粒子可以是元素声明或其他模型组。模型组本身有一个基数,可以使用 minOccurs 和 maxOccurs 属性对其进行优化。这些特征使模型组非常强大。

    XML 模式支持的三个模型组分别为:

    • Sequence - (a , b)* - 在 sequence 模型组中声明的子元素必须以模式中定义的同样顺序出现在相应的 XML 实例中。Sequence 模型组的基数范围从 0 到无限大。通过递归方式,sequence 模型组还可以进一步包含 Sequence 或 choice 模型组。
    • Choice - (a | b)* - 表示在 choice 模型组中声明的子元素集中,必须有一个元素出现在相应的 XML 实例中。Choice 模型组的基数范围从 0 到无限大。通过递归方式, choice 模型组可以进一步包含 Sequence 或Choice 模型组。
    • all - {a , b}?- 表示在 all 模型组中声明的整个子元素集必须出现在相应的 XML 实例中,但与 sequence 模型组不同的是,顺序并不重要。因此,子元素可以任何顺序出现。all 模型组的基数只能为 0 或 1。all 模型组只能包含元素声明而不能包含任何其他模型组。

    这些模型组既可以内联方式声明,也可以全局声明(一个包含名称并可重用的 <schema> 结构的直接子项)方式声明。必须在 <group> 结构中声明全局模型组,您可以以后按其名称引用它。但与内联模型组不同的是,不能在全局声明的模型组上声明 minOccurs/maxOccurs 属性。如果需要,可以在引用全局声明的模型组时使用 minOccurs/maxOccurs 属性。例如:

    <xsd:group name="globalDecl">
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" />
    <xsd:element name="child2" type="xsd:string" />
    </xsd:sequence>
    </xsd:group>
    

    随后,可以在需要时使用 group 结构以及 minOccurs/maxOccurs 属性引用全局声明的模型组:

    <xsd:group ref="globalDecl" maxOccurs="unbounded">
    

    为更好地了解模型组,以下提供了一个复杂示例:

    ((a | b)* , c+)?
    
    <xsd:element name="complexModelGroup">
    <xsd:complexType>
    
    <xsd:sequence minOccurs="0" maxOccurs="1">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
    <xsd:element name="a" type="xsd:string" />
    <xsd:element name="b" type="xsd:string" />
    </xsd:choice>
    <xsd:element name="c" type="xsd:string" minOccurs="1" maxOccurs="unbounded">
    </xsd:sequence>
    
    </xsd:complexType>
    </xsd:element>
    

    complexType 叙述

    您现在拥有足够的信息来编写一个简单的 XML 文档模式。但 XML 模式中的许多高级概念仍有待介绍。

    complexType 是 XML 模式中其他强大的结构之一。您除了可以声明所有四个包含或不包含属性的内容模型以外,还可以通过继承已经声明的 complexType 以派生出新的 complexType。因此,派生的 complexType 既可以将更多声明添加到由基础 complexType 继承而来的声明(使用 extension),也可以限制基础 complexType 中的声明(使用 restriction)。

    可以使用 simpleContent 或 complexContent 扩展或限制 complexType。具有 simpleContent 的 complexType 声明一个包含或不包含属性的 TextOnly 内容模型。具有 complexContent 的 complexType 可用于声明其它三个包含或不包含属性的内容模型(ElementOnly、Mixed 或 Empty)。

    扩展 complexType

    simpleContent

    图 2
    图 2:只能通过扩展具有 simpleContent 的 complexType 才能添加属性。

    具有 simpleContent 的 complexType 可以扩展 simpleType 具有 simpleContent 的 complexType。如图 2 中所示,在派生的 complexType 中,允许您执行的唯一操作是添加属性。例如:

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
        
    <xsd:complexType name="DerivedType1">
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="att1" type="xsd:string" use="required" />
    </xsd:extension>
    </xsd:simpleContent>
    </xsd:complexType>
    
    <xsd:complexType name="DerivedType2">
    <xsd:simpleContent>
    <xsd:extension base="tns:DerivedType1">
    <xsd:attribute name="att2" type="xsd:string" use="required" />
    </xsd:extension>
    </xsd:simpleContent>
    </xsd:complexType>
    
    <xsd:element name="SCExtension">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Derived1" type="tns:DerivedType1" />
    <xsd:element name="Derived2" type="tns:DerivedType2" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中:

    1. DerivedType1 基于内置的 simpleType string 扩展,并添加了一个属性 attr1。
    2. DerivedType2 继承基础 DerivedType1(它是一个具有 simpleContent 的 complexType)中的属性 attr1,并添加一个属性 attr2。

    对应于以上模式的 XML 实例如下:

    <SCExtension xmlns="http://inheritance-ext-res"
    xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
    xsi:schemaLocation="http://inheritance-ext-res CTSCExt.xsd">
    
    <Derived1 att1="val">abc</Derived1>
    <Derived2 att1="val" att2="val">def</Derived2>
      
    </SCExtension>
    

    complexContent

    图 3
    图 3:具有 complexContent 的 complexType 可用于扩展模型组以及添加属性。

    具有 complexContent 的 complexType 可以扩展 complexType 具有 complexContent 的 complexType。如图 3 所示,在派生的 complexType 中,允许您添加属性以及扩展模型组。例如:

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    
    <!— (child1)+ —>
    <xsd:complexType name="BaseType">
    <xsd:sequence maxOccurs="unbounded">
    <xsd:element name="child1" type="xsd:string" />
    </xsd:sequence>
    <xsd:attribute name="att1" type="xsd:string" use="required" />
    </xsd:complexType>
    
    <!— ((child1)+ , (child2 | child3)) —>
    <xsd:complexType name="DerivedType">
    <xsd:complexContent>
    <xsd:extension base="tns:BaseType">
    <xsd:choice>
    <xsd:element name="child2" type="xsd:string" />
    <xsd:element name="child3" type="xsd:string" />
    </xsd:choice>
    <xsd:attribute name="att2" type="xsd:string" use="required" />
    </xsd:extension>
    </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:element name="CCExtension">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Base" type="tns:BaseType" />
    <xsd:element name="Derived" type="tns:DerivedType" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中:

    1. DerivedType 继承基础 complexType 中的 sequence 模型组,并添加一个 choice 模型组,从而生成派生的 complexType 的最终内容模型- ((child1)+ , (child2 | child3))。
    2. DerivedType 继承 BaseType 中的属性 attr1,并添加属性 attr2。

    对应于以上模式的 XML 实例如下:

    <CCExtension xmlns="http://inheritance-ext-res"
    xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
    xsi:schemaLocation="http://inheritance-ext-res CTCCExt.xsd">
    
    <Base att1="val">
    <child1>This is base</child1>
    <child1>This is base</child1>
    </Base>
      
    <Derived att1="val" att2="val">
    <child1>This is inherited from base</child1>
    <child1>This is inherited from base</child1>
    <child1>This is inherited from base</child1>
    <child3>This is added in the derived</child3>
    </Derived>
    
    </CCExtension>
    

    限制 complexType

    simpleContent

    图 4
    图 4:具有 simpleContent 的 complexType 可用于限制数据类型和属性。

    具有 simpleContent 的 complexType 只能限制具有 simpleContent 的 complexType。如图 4 中所示,在派生的 complexType 中,可以限制基类的 simpleType,以及限制基类中的属性的类型和使用(可选、强制等)。例如:

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
        
    <xsd:complexType name="BaseType">
    <xsd:simpleContent>
    <xsd:extension base="xsd:string">
    <xsd:attribute name="att1" type="xsd:string" use="optional" />
    <xsd:attribute name="att2" type="xsd:integer" use="optional" />
    </xsd:extension>
    </xsd:simpleContent>
    </xsd:complexType>
    
    <xsd:complexType name="DerivedType">
    <xsd:simpleContent>
    <xsd:restriction base="tns:BaseType">
    <xsd:maxLength value="35" />
    <xsd:attribute name="att1" use="prohibited" />
    
    <xsd:attribute name="att2" use="required">
    <xsd:simpleType>
    <xsd:restriction base="xsd:integer">
    <xsd:totalDigits value="2" />
    </xsd:restriction>
    </xsd:simpleType>
    </xsd:attribute>
    
    </xsd:restriction>
    </xsd:simpleContent>
    </xsd:complexType>
    
    <xsd:element name="SCRestriction">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Base" type="tns:BaseType" />
    <xsd:element name="Derived" type="tns:DerivedType" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中:

    1. 您将基类的 simpleType 内容(字符串类型)限制为派生的 simpleType 中一个长度为 35 的字符串。
    2. 您禁止从基类中继承属性 att1。
    3. 您将属性 att2 的类型限制为一个 2 位整数,并使其从可选变为强制。

    对应于以上模式的 XML 实例如下:

    <SCRestriction xmlns="http://inheritance-ext-res"
    xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
    xsi:schemaLocation="http://inheritance-ext-res CTSCRes.xsd">
    
    <Base att1="val">This is base type</Base>
    <Derived att2="12">This is restricted in the derived</Derived>
      
    </SCRestriction>
    

    complexContent

    图 5
    图 5:具有 complexContent 的 complexType 可用于限制模型组和属性。

    具有 complexContent 的 complexType 可以限制 complexType 具有 complexContent 的 complexType。如图 5 中所示,在派生的 complexType 中,您必须重复基类中的整个内容模型并在需要时按照要求对其进行限制。可以按照限制 simpleContent 的同一方法来限制属性。例如:

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    
    <xsd:complexType name="BaseType">
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" maxOccurs="unbounded" />
    <xsd:element name="child2" type="xsd:string"/>
    </xsd:sequence>
    <xsd:attribute name="att1" type="xsd:string" use="optional" />
    </xsd:complexType>
    
    <xsd:complexType name="DerivedType">
    <xsd:complexContent>
    <xsd:restriction base="tns:BaseType">
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" maxOccurs="4" />
    
    <xsd:element name="child2">
    <xsd:simpleType>
    <xsd:restriction base="xsd:string">
    <xsd:maxLength value="35" />
    </xsd:restriction>
    </xsd:simpleType>
    </xsd:element>
    
    </xsd:sequence>
    <xsd:attribute name="att1" type="xsd:string" use="prohibited" />
    </xsd:restriction>
    </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:element name="CCRestriction">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Base" type="tns:BaseType" />
    <xsd:element name="Derived" type="tns:DerivedType" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中:

    1. 您将 DerivedType(从 BaseType 继承)中的 child1 的基数从无限大限制为 4。
    2. 您将 DerivedType(从 BaseType 继承)中的 child2 的类型限制为一个长度为 35 的字符串。
    3. 您禁止从 BaseType 继承属性 att1。

    对应于以上模式的 XML 实例如下:

    <CCRestriction xmlns="http://inheritance-ext-res"
    xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
    xsi:schemaLocation="http://inheritance-ext-res CTCCRes.xsd">
    
    <Base att1="val">
    <child1>This is base type</child1>
    <child2>This is base type</child2>
    </Base>
      
    <Derived>
    <child1>This is restricted in the derived</child1>
    <child2>This is restricted in the derived</child2>
    </Derived>
      
    </CCRestriction>
    

    组装模式

    导入、包含和 可变式效果

    许多 Java 项目都涉及多个不同的类和程序包,而不只是一个大的 Java 文件,这是因为模块化可以方便代码的重用、读取和维护。随后,必须将必需的导入语句加入到类中,然后才能使用它们。同样,在 XML 模式中,您必须在各种不同命名空间中管理不同的模式,并需要将必需的导入语句加入到模式中,然后才能使用它们。

    可以使用 <import/> 和 <include/> 模式结构组装 XML 模式,当然,以下应是该模式中位于其他任何声明之前的第一个语句:

    <schema>
    <import namespace="foo" schemaLocation="bar.xsd" />
    <include schemaLocation="baz.xsd" />
      ...
    </schema>
    

    当导入的模式具有 targetNamespace 时,将使用 <import />,而当包含的模式未声明 targetNamespace 时,将使用 <include />。

    下面,我们将介绍一个示例,该示例涉及两个模式 A 和 B,且 A 引用 B 中声明的项目。

    情况 I 
    如果两个模式都有 targetNamespace,且模式 A 的 targetNamespace (tnsA) 不同于模式 B 的 targetNamespace (tnsB),则 A 必须导入 B。

    <import namespace="tnsB" schemaLocation="B.xsd">
    

    但 A 导入 B 时和 A 包含 B 时不指定命名空间是一个错误。

    情况 II
    如果两个模式都包含 targetNamespace,且模式 A 的 targetNamespace (tnsAB) 与模式 B 的 targetNamespace (tnsAB) 相同,则 A 必须包含 B。

    <include schemaLocation="B.xsd">
    

    A 导入 B 是错误的。

    情况 III
    如果模式 A 和 B 都没有 targetNamespace。这种情况下,A 必须包含 B。

    <include schemaLocation="B.xsd" />
    

    情况 IV
    如果模式 A 没有 targetNamespace,而模式 B 包含 targetNamespace (tnsB),则 A 必须导入 B。

    <import namespace="tnsB" schemaLocation="B.xsd" />
    

    A 包含 B 是错误的,这是因为 B 包含一个 targetNamespace。

    情况 V
    如果模式 A 包含 targetNamespace (tnsA),而模式 B 不包含 targetNamespace,情况又将如何?A 应包含 B。但如果我认为在本例中,A 应导入 B,情况将如何?实际上,在这种情况下,A 可以导入或包含 B,且这两个操作都是合法的,但效果并不相同。

    如果 A 包含 B,则所包含的来自 B 的所有项目将获取 A 的命名空间。这样的包含被称作 可变式 包含。

    如果您不希望发生这样的可变式效果,则必须在不指定命名空间情况下完成导入。没有 namespace 属性的导入允许对不包含目标命名空间的组件进行非限定性引用。

    <import schemaLocation="B.xsd">
    

    多次导入或包含一个模式不会产生错误,这是因为模式处理器可以检测这种情况并不再加载已加载的模式。因此,A.xsd 导入 B.xsd 和 C.xsd 并不产生错误;B.xsd 和 C.xsd 各自单独导入 A.xsd。循环引用不会产生错误,但强烈建议您不要使用它。

    顺便说明的是,一个类似 <import /> 的简单导入也是合法的。该方法只允许对不包含目标命名空间的外部组件进行非限定性引用,而不提供任何有关其所在位置的信息提示。模式处理器将利用某种机制提示出错或查找未知项目,因模式处理器而异。但使用 <include /> 是非法的。

    经验法则:

    1. <include/> - 它的作用与在包含模式中以内联方式定义被包含的模式相当。
    2. <import/> -如果被导入的模式与导入模式的 targetNamespace 不同则始终使用 <import/>。

    重新定义模式

    您可能并不总想用其原始格式组装模式。例如,您可能需要修改从模式中导入的组件。在此类情况下,当我们需要重定义声明而不更改其名称时,我们使用重定义组件完成这一过程,要重定义的模式必须满足以下限制条件:(a) 与 重定义模式文档具有相同的 targetNamespace,(b) 根本没有 targetNamespace,这种情况下,被重定义模式文档将转变为重定义模式文档的 targetNamespace。

    例如:

    actual.xsd

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    
    <xsd:complexType name="BaseType">
    <xsd:sequence>
    <xsd:element name="child1" type="xsd:string" />
    </xsd:sequence>
    <xsd:attribute name="att1" type="xsd:string" use="required" />
    </xsd:complexType>
    
    <xsd:complexType name="DerivedType">
    <xsd:complexContent>
    <xsd:extension base="tns:BaseType">
    <xsd:choice>
    <xsd:element name="child2" type="xsd:string" />
    <xsd:element name="child3" type="xsd:string" />
    </xsd:choice>
    <xsd:attribute name="att2" type="xsd:string" use="required" />
    </xsd:extension>
    </xsd:complexContent>
    </xsd:complexType>
    
    </xsd:schema>
    

    redefine.xsd

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://inheritance-ext-res"
    xmlns:tns="http://inheritance-ext-res"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
                
    <xsd:redefine schemaLocation="actual.xsd">
    <xsd:complexType name="DerivedType">
    <xsd:complexContent>
    <xsd:extension base="tns:DerivedType">
    <xsd:sequence>
    <xsd:element name="child4" type="xsd:string" />
    </xsd:sequence>
    </xsd:extension>
    </xsd:complexContent>
    </xsd:complexType>
    </xsd:redefine>
    
    <xsd:element name="Redefine">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Base" type="tns:BaseType" />
    <xsd:element name="Derived" type="tns:DerivedType" />
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中:

    1. 您在未更改其名称的情况下,通过向内容模型中添加一个或多个元素重新定义了名称为 DerivedType 的 complexType。
    2. 不在重定义模式中重新定义基类,它将按原样继承。

    注意,重定义类型时,类型名称并不更改。所以,重定义的类型将其自身用作基类。

    在以上示例中,我们重新定义了一个名为 DerivedType 的 complexType 而未更改其名称。重定义 DerivedType 时,对“DerivedType”的任何引用(例如,base="tns:DerivedType")都被认为是引用实际的 DerivedType。重定义类型后,对 DerivedType 的任何引用都被认为是引用重定义后的类型。

    对应于以上重新定义的模式的 XML 实例如下:

    <Redefine xmlns="http://inheritance-ext-res"
    xmlns:xsi="http://www.w3.org/2001/XML Schema-instance"
    xsi:schemaLocation="http://inheritance-ext-res redefine.xsd">
    
    <Base att1="val">
    <child1>This is base type</child1>
    </Base>
      
    <Derived att1="val" att2="val">
    <child1>This is inherited from the base as is</child1>
    <child2>This is added in the derived</child2>
    <child4>This is added when redefining</child4>
    </Derived>
    
    </Redefine>
    

    约束

    身份约束

    使用 XML 模式,您可以对元素和属性的内容实施唯一性约束,这可以保证指定元素或属性的值在实例文档中是唯一的。实施唯一性时,必须要有一个其值需要进行唯一性检查的项目,例如,ISBN 号。确定项目后,必须确定一个集合(例如,图书集),以在其中对这些选定的项目的值进行唯一性检查。

    XML 模式为实施唯一性约束提供了两个结构: unique 和 keyUnique 确保当指定值不为空时,它们必须在定义的集合中是唯一的;key 确保指定值始终不为空,并在定义的集合中是唯一的。

    还有一个结构 — keyref,它指向某个已定义的键。Keyref 确保 keyref 指向的键集中存在 keyref 中指定项目的值。

    这三个结构的全都具有相同的语法(它们全都使用选择器和域),但含义不同。选择器用于定义集合,以在其中实施在其中实施唯一性,(多个域用于定义一个组合项目)用于定义项目,以对其值进行唯一性检查。选择器的值均为 XPath 表达式。XPath 表达式不支持缺省命名空间,因此必须通过显式使用绑定到相应命名空间(如果命名空间中存在元素/属性)的前缀以使 XPath 表达式支持命名空间。例如:

    <?xml version="1.0"?>
    <xsd:schema targetNamespace="http://identity-constraint"
    xmlns:tns="http://identity-constraint"
    xmlns:xsd="http://www.w3.org/2001/XML Schema"
    elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    
    
    <xsd:complexType name="BookType">
    <xsd:sequence>
    <xsd:element name="title" type="xsd:string" />
    <xsd:element name="half-isbn" type="xsd:string" />
    <xsd:element name="other-half-isbn" type="xsd:float" />
    </xsd:sequence>
    </xsd:complexType>
    
    <xsd:element name="Books">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="Book" type="tns:BookType" maxOccurs="unbounded" />
    </xsd:sequence>
    </xsd:complexType>
    
    <xsd:key name="isbn">
    <xsd:selector xpath=".//tns:Book" />
    <xsd:field xpath="tns:half-isbn" />
    <xsd:field xpath="tns:other-half-isbn" />
    </xsd:key>
    
    </xsd:element>
    
    </xsd:schema>
    

    在以上模式中,我们声明了一个名为“isbn”的键,它表示由“field 指定的组合值不得为空,并在由 selector 指定的图书集中是唯一的”。

    唯一粒子属性 (UPA) 约束

    UPA 约束确保按以下方式指定每个元素的内容模型:在验证 XML 实例时,不存在模糊性,且可以明确确定正确的元素声明以进行验证。例如,以下模式违反了 UPA 约束:

    <xsd:element name="upa">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="a" minOccurs="0"/>
    <xsd:element name="b" minOccurs="0"/>
    <xsd:element name="a" minOccurs="0"/>
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    

    这是因为在以上模式的相应 XML 实例中:

    <upa>
    <a/>
    </upa>
    

    不能确定 XML 实例中的元素“a”对应于模式中的哪个元素声明 - 是位于“b”的元素声明之前“a”的元素声明,还是位于“b”的元素声明之后的“a”的元素声明。该限制使您只能编写上面的 XML 实例类型的 XMLSchema。在本示例中,如果您只将元素“b”的 minOccurs 设置为任何大于 0 的值,则不会违反 UPA。

    因此,以下是一个有效模式:

    <xsd:element name="upa">
    <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="a" minOccurs="0"/>
    <xsd:element name="b" minOccurs="1"/>
    <xsd:element name="a" minOccurs="0"/>
    </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    

    这是因为在以上模式的相应 XML 实例中:

    <upa>
    <a/>
    <b/>
    </upa>
    

    显而易见的是,XML 实例中的元素“a”实际上是“a”的元素声明(它位于该模式中“b”的元素声明之前)实例。

    结论

    现在,您已经完成了本系列,您应了解以下内容:

    1. XML 和 XML 模式中的命名空间概念
    2. XML 模式中支持的标量数据类型以及如何使用 simpleType 进一步限制它们
    3. 元素内容、内容模型、模型组、粒子、扩展和限制 complexType、组装模式、标识约束和 UPA(用于定义和约束 XML 的结构)。

    至此,您应已经较好地掌握了 XML 模式。

  • 相关阅读:
    [WPF]WPF3.5 SP1 TreeView的Bug
    2010年自我总结
    LINQ to SQL 异常:SQL Server does not handle comparison of NText, Text, Xml, or Image data types
    [翻译] javascript缩进
    【转】疑难解答:调试 Windows 服务
    【翻译】MSDN文档对类DefaultValueAttribute的描述有些混淆
    二叉排序树——算法系列
    索引查找——算法系列
    android软电话开发预备知识
    adb server is out of date.killing
  • 原文地址:https://www.cnblogs.com/lengzhijun/p/4209982.html
Copyright © 2011-2022 走看看