是否可以为XSD架构创建XSD架构,或者对元素定义进行限制?怎么样?

时间:2013-06-27 15:10:37

标签: xml xsd

我的目标是对我的XSD元素定义进行简单限制:我想定义一个元素,以便

    所有元素定义<xs:annotation><xs:documentation> 都需要
  1. </xs:documentation></xs:annotation>
  2. “声明”和“last_modified”属性已添加到<xs:element>,“note_author”和“note_added”属性已添加到<xs:documentation>元素。
  3. 通过以下内容,我可以让Schema 2进行验证,但我无法执行上面提到的规则,我想在Schema 1中声明。

    我希望使用经过修改的,经过验证的XSD架构(架构2)实现的目标:

    SCHEMA2。

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
               xmlns:ds="http://documentation_schema">
    
      <xs:import namespace="http://documentation_schema" 
                 schemaLocation="documentation_schema.xsd"/>
    
      <xs:element name="document" 
                  ds:created="2013-06-20" 
                  ds:last_modified="2013-06-20">
    
        <xs:annotation>
          <xs:documentation ds:note_author="xsd_user1" 
                            ds:note_added="2013-06-20">
          The root element for a document
          </xs:documentation>
        </xs:annotation>
    
        <xs:complexType>
          <xs:sequence maxOccurs="unbounded">
            <xs:element ref="subelement"/>
          </xs:sequence>    
        </xs:complexType>
      </xs:element>
    
      <xs:element name="subelement" type="xs:string"  
                  ds:created="2013-06-20" 
                  ds:last_modified="2013-07-20">
    
        <xs:annotation>
          <xs:documentation ds:note_author="xsd_user1" 
                            ds:note_added="2013-06-20">
          A subelement child of document
          </xs:documentation>
    
          <xs:documentation ds:note_author="xsd_user2" 
                            ds:note_added="2013-07-20">
          changed from complex to string type
          </xs:documentation>
        </xs:annotation>`
      </xs:element>
    
    </xs:schema>
    

    架构1(documentation_schema) - 我想要验证架构2的架构:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
               targetNamespace="http://documentation_schema">
    
      <xs:attribute name="created" type="xs:date"/>
    
      <xs:attribute name="last_modified" type="xs:date"/>
    
      <xs:attribute name="note_added" type="xs:date"/>
    
      <xs:attribute name="note_author">
        <xs:simpleType>
          <xs:restriction base="xs:token">
            <xs:enumeration value="xsd_user1"/>
            <xs:enumeration value="xsd_user2"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    
    </xs:schema>
    

1 个答案:

答案 0 :(得分:4)

好问题!

应该提出几点:

  • 首先,正如我猜你已经知道的那样(虽然问题的一些读者和这个答案可能没有),但你的架构文件1已经合法。因此,您不需要 来修改架构文档的架构,以使其合法化。但是,如果我理解正确的话,你希望它不仅仅是有效的;你想要它的变体,其中元素声明在没有xs:documentation元素的情况下发生,或者没有ds:added和ds:last_modified属性,无效

  • 其次,可以按照您描述的方式修改XSD架构文档的XSD架构,并且原则上可以根据架构文档的修改架构验证架构文档。

    但是,允许模式验证器具有任意名称空间中某些模式组件的内置知识,并且它们 required 具有XSD名称空间的内置知识。因此,符合模式验证器可以查看验证模式文档1的请求,比如说#A;我已经知道我需要了解的关于命名空间http://www.w3.org/2001/XMLSchema的所有内容,我不需要阅读用户提供的架构文档&#34;,然后不强制执行您指定的其他约束。

    具体地说,在我的测试中,我能够使用Xerces J来针对模式文档的修改模式验证模式文档,但是Saxon似乎忽略了修改并且规则模式文档有效,即使元素声明缺少必需的属性。

  • 同样,在根据您编写的模式验证文档时,不可能要求您的XSD验证程序反对不符合您的高要求的模式文档。

有了这些背景点,这就是你需要做的事情。

  1. 需要将ds架构导入到架构文档中1.导入它意味着您可以将对ds:added等属性的引用添加到您的类型中在模式文档1中声明 - 也就是说,它将其导入到为目标名称空间定义的模式中。它对用于验证模式文档的模式没有影响(模式是命名空间http://www.w3.org/2001/XMLSchema的模式)。

  2. 您需要创建一个模式来修改模式文档的标准模式,而不仅仅是通过添加新组件,而是通过重新定义或覆盖模式文档的现有模式中的组件。有两种方法可以做到这一点:使用xs:redefine,和(在XSD 1.1中)使用xs:override。在XSD 1.1中,不推荐使用xs:redefine,因为它的规范已被证明是不完整和/或不一致的,并且对于某些使用它的方式,跨处理器的互操作性很差。

  3. 您需要使用XSD验证程序根据架构文档的修改架构验证架构文档。如上所述,这可能不适用于所有验证器。如果您在处理XSD验证器时遇到问题,您可能需要考虑编写Schematron架构来强制执行您提到的一些约束,并将Schematron验证构建到您的工作流程中。 (Schematron的一个优点是,只验证文档中的一些独立方面非常容易。在某些情况下这可能是一个缺点,但在这个或其他需要增加一点验证的情况下则不是。如果您的用户名表明您是XSLT用户,Schematron可能会对您感到很自然。)

  4. 作为测试,我使用xs:override来修改XSD 1.1的架构文档的架构;架构文档如下所示,我希望这些评论能够清楚地说明发生了什么。如果您只能访问XSD 1.0处理器,则需要使用xs:redefine;一些细节将会改变。

    <?xml version='1.0'?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
               xmlns:ds="http://documentation_schema"
               blockDefault="#all"
               elementFormDefault="qualified" 
               xml:lang="en"
               targetNamespace="http://www.w3.org/2001/XMLSchema"
               version="Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp ">
    
      <xs:annotation>
        <xs:documentation>
          This schema document redefines some things in the schema for 
          schema documents.  
          First we import the ds and xml namespaces.
        </xs:documentation>
      </xs:annotation>
    
      <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
      <xs:import namespace="http://documentation_schema"
                 schemaLocation="xslt_user_schema2.xsd">
        <xs:annotation>
          <xs:documentation>
            Get access to the ds:* attributes.
          </xs:documentation>
        </xs:annotation>
      </xs:import>
    
      <xs:annotation>
        <xs:documentation>
          Then we include the schema for schema documents defines in XSD 1.1, with
          some modifications.  
        </xs:documentation>
      </xs:annotation>
    
      <xs:override schemaLocation="sfsd-11.xsd">
        <xs:annotation>
          <xs:documentation>
            The schema document "sfsd-11.xsd" is our local copy of the 
            XSD 1.1 schema for schema documents.  
          </xs:documentation>
        </xs:annotation>
    
        <xs:element name="documentation" id="documentation" 
                    type="xs:documentation-extended">
          <xs:annotation>
            <xs:documentation>
              Here, we change the xs:documentation element from using
              a local complex type to using a named type (declared below).  
            </xs:documentation>
          </xs:annotation>
        </xs:element>
    
        <xs:element name="annotation" id="annotation">
          <xs:annotation>
            <xs:documentation>
              Next, we require xs:annotation elements to contain 
              at least one xs:documentation element.
            </xs:documentation>
          </xs:annotation>
    
          <xs:complexType>
            <xs:complexContent>
              <xs:extension base="xs:openAttrs">
                <!--* modified the content model to require at least one 
                    * occurrence of xs:documentation 
                    *-->
                <xs:sequence>
                  <xs:element ref="xs:appinfo" minOccurs="0" maxOccurs="unbounded"/>
                  <xs:element ref="xs:documentation"/>
                  <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="xs:appinfo"/>
                    <xs:element ref="xs:documentation"/>
                  </xs:choice>
                </xs:sequence>            
                <xs:attribute name="id" type="xs:ID"/>
              </xs:extension>
            </xs:complexContent>
          </xs:complexType>
        </xs:element>
    
        <!--* Finally, we override the complex type used for all forms 
            * of element declarations, by including the attribute group
            * xs:schema-documentation-attributes (defined below).
            * Note that we cannot include references to the attributes
            * directly, because the default schema for schema documents
            * doesn't import the ds namespace.  One level of indirection,
            * however, suffices to solve the problem.
            *-->
    
        <xs:complexType name="element" abstract="true">
          <xs:annotation>
            <xs:documentation>
              The element element can be used either
              at the top level to define an element-type binding globally,
              or within a content model to either reference a globally-defined
              element or type or declare an element-type binding locally.
            The ref form is not allowed at the top level.</xs:documentation>
            <xs:documentation>
              This modification of the type adds two required attributes:
              ds:added and ds:last_modified.  They will be inherited by
              all the various restrictions of this type.
            </xs:documentation>
          </xs:annotation>
          <xs:complexContent>
            <xs:extension base="xs:annotated">
              <xs:sequence>
                <xs:choice minOccurs="0">
                  <xs:element name="simpleType" type="xs:localSimpleType"/>
                  <xs:element name="complexType" type="xs:localComplexType"/>
                </xs:choice>
                <xs:element name="alternative" type="xs:altType" 
                            minOccurs="0" maxOccurs="unbounded"/>
                <xs:group ref="xs:identityConstraint" minOccurs="0"
                          maxOccurs="unbounded"/>
              </xs:sequence>
              <xs:attributeGroup ref="xs:defRef"/>
              <xs:attribute name="type" type="xs:QName"/>
    
              <xs:attribute name="substitutionGroup">
                <xs:simpleType>
                  <xs:list itemType="xs:QName"/>
                </xs:simpleType>
              </xs:attribute>
              <xs:attributeGroup ref="xs:occurs"/>
              <xs:attribute name="default" type="xs:string"/>
              <xs:attribute name="fixed" type="xs:string"/>
              <xs:attribute name="nillable" type="xs:boolean" use="optional"/>
              <xs:attribute name="abstract" type="xs:boolean" default="false"
                            use="optional"/>
              <xs:attribute name="final" type="xs:derivationSet"/>
              <xs:attribute name="block" type="xs:blockSet"/>
              <xs:attribute name="form" type="xs:formChoice"/>
              <xs:attribute name="targetNamespace" type="xs:anyURI"/>
              <!--* add the ds:* attributes *-->
              <xs:attributeGroup ref="xs:schema-documentation-attributes"/>
              <!--* end of added material. *-->
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
    
      </xs:override>
    
      <xs:complexType name="documentation-extended" mixed="true">
        <xs:annotation>
          <xs:documentation>
            This complex type is just like the usual type for the 
            xs:documentation element, except that it reuqires the 
            ds:note_author and ds:note_added attributes.
          </xs:documentation>
        </xs:annotation>
        <xs:sequence minOccurs="0" maxOccurs="unbounded">
          <xs:any processContents="lax"/>
        </xs:sequence>
        <xs:attribute name="source" type="xs:anyURI"/>
        <xs:attribute ref="xml:lang"/>
        <!--* additions ... *-->
        <xs:attribute ref="ds:note_author" use="required"/>
        <xs:attribute ref="ds:note_added" use="required"/>
        <!--* end added material *-->
        <xs:anyAttribute namespace="##other" processContents="lax"/>
      </xs:complexType>
    
      <xs:attributeGroup name="schema-documentation-attributes">
        <xs:annotation>
          <xs:documentation>
            This attribute group serves to include the two
            attributes specified in the complex type for
            element declarations.
          </xs:documentation>
        </xs:annotation>
        <xs:attribute ref="ds:created" use="required"/>
        <xs:attribute ref="ds:last_modified" use="required"/>
      </xs:attributeGroup> 
    
    </xs:schema>
    

    添加以回应评论。

      

    1(a)中。我仍然需要有一个用于验证模式文档的模式的本地副本,对吧? (在你的情况下:sfsd-11.xsd,在我的例子中:在w3.org/2001/XMLSchema上找到的模式?[但是我选择命名吗?)?

    要使用覆盖(在XSD 1.1中)或重新定义(在1.0或1.1中),您需要指向要修改的模式的schemaLocation。如果您有架构文档架构的本地副本,您当然可以指向它,但同样可以指向W3C服务器上的副本。所以:不,你不需要&#34;需要&#34;有本地副本。但是你很可能想要:W3C的服务器每次解析XML文档时都会尝试取消引用DTD和模式文档,而W3C的系统管理员通过让服务器响应来做出响应这种要求非常缓慢。如果这样的本地副本可能更方便,即使它在任何意义上都不需要。

      

    1(b)中。当我尝试保存在w3.org/2001/XMLSchema中找到的模式的本地副本时,我得到该模式的验证错误,并引用了&#39; xs:发生&#39;已经宣布了。&#39;如果我注释掉那个属性组,我会得到类似的错误。

    当您尝试保存时?听起来好像您的文件系统正在对您保存的文件执行模式验证;这将是新颖的行为。我怀疑你看到的验证错误是在其他一些情况下出现的;在不知道验证器试图做什么以及如何调用它的情况下,很难说出这里发生了什么。有关属性组xs:的消息已经被声明,表明您的验证器正在查看模式文档的模式两次;要么是因为它了解了内置的命名空间(在这种情况下,您可能无法使验证器完全使用修改后的模式),或者因为您放置模式的方式有误一起,或者因为调用验证器的方式有误。

      

    1(c)。请注意,我已将XMLSchema.dtd标头包含在我的本地保存模式的顶部(并在本地保存了dtd)我的本地模式的属性:

        <!DOCTYPE schema SYSTEM "XMLSchema.dtd"> 
        <xs:schema targetNamespace="w3.org/2001/XMLSchema"
                   blockDefault="#all" 
                   elementFormDefault="qualified" 
                   version="1.0" 
                   xmlns:xs="w3.org/2001/XMLSchema"
                   xml:lang="EN" 
                   xmlns:hfp="w3.org/2001/XMLSchema-hasFacetAndProperty"
                   finalDefault="" 
                   attributeFormDefault="unqualified"> 
    

    这里没有明显的问题。严格来说,文件类型声明并不是必需的,但如果您没有遇到“无法找到DTD”的话。错误,它可能没有任何伤害。

      

    1(c)(续)当我删除xmlns时:xs =&#34; w3.org/2001/XMLSchema" ;; (我怀疑它会摆脱重复的定义错误,我得到另一个错误,指出&#34;元素&#39; xs:schema&#39;没有声明名为&#39; xmlns:hfp&#39的属性;&#34;你或任何人可以告诉我这里我做错了什么吗?

    您有一个文档,几乎在每个元素上使用名称空间前缀xs。您想要删除该前缀的名称空间绑定。

    使XSD验证器使用模式文档的模式的修改形式,这是使用XSD的高级主题。 (只要你使用语言L来描述并可能修改语言L,就很容易将自己变成对象语言和元语言之间的混淆。请问离你最近的大师他们需要多长时间才能理解第一个元语言。他们研究过的循环翻译。)

    如果您正处于使用XML和XSD的阶段,您对在一个架构文档中删除命名空间声明的可能影响有任何疑问,您可能会发现您执行的任务非常具有挑战性。我不会说你不应该花时间,因为我不会告诉青少年不要花时间重建引擎。它可能很有趣,你可能会学到很多东西。但是,如果你不是以此为目的,那么你需要知道它不会快速或简单。通过这种方式摆弄命名空间声明,你不太可能让它工作。 (在此背景下,我建议您阅读the story of Tom Knight and the Lisp Machine。)