【问题标题】:Is it possible to create an XSD schema for an XSD schema, or place restrictions on element definitions? How?是否可以为 XSD 架构创建 XSD 架构,或者对元素定义施加限制?如何?
【发布时间】:2013-07-02 10:28:29
【问题描述】:

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

  1. 所有元素定义都需要<xs:annotation><xs:documentation></xs:documentation></xs:annotation>
  2. “declared”和“last_modified”属性被添加到<xs:element>,“note_author”和“note_added”属性被添加到<xs:documentation>元素。

使用下面的内容,我可以让 Schema 2 进行验证,但我无法执行上面提到的规则,我想在 Schema 1 中声明这些规则。

我想通过修改、验证的 XSD 架构(架构 2)实现的示例:

架构2。

<?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>

Schema 1 (documentation_schema) -- 我想要验证 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>

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    好问题!

    需要说明几点:

    • 首先,我猜您已经知道(尽管该问题和该答案的某些读者可能不知道),您的架构文档 1 已经是合法的。因此,您不需要需要修改架构文档的架构以使其合法。但是,如果我对您的理解正确,那么您不仅希望它有效;您希望它的变体在没有 xs:documentation 元素或没有 ds:added 和 ds:last_modified 属性的情况下发生元素声明,为 invalid

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

      但是模式验证器可以对任意命名空间中的某些模式组件具有内置知识,并且它们要求具有 XSD 命名空间的内置知识。因此,符合模式的验证器可以看到验证模式文档 1 的请求,说“啊哈,我已经知道我需要知道的关于命名空间 http://www.w3.org/2001/XMLSchema 的所有信息,我不需要阅读用户提供的模式文档” ,然后不强制执行您指定的其他约束。

      具体来说,在我的测试中,我能够使用 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 很自然。)

    作为测试,我使用 xs:override 来修改 XSD 1.1 架构文档的架构;模式文档如下所示,我希望 cmets 能够合理地弄清楚发生了什么。如果您只能访问 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>
    

    添加以响应 cmets。

    1(a)。我仍然需要用于验证架构文档的架构的本地副本,对吗? (在您的情况下:sfsd-11.xsd,在我的情况下:在 w3.org/2001/XMLSchema 找到的架构?[命名但我选择命名它?)?

    要使用覆盖(在 XSD 1.1 中)或重新定义(在 1.0 或 1.1 中),您需要指向正在修改的架构的 schemaLocation。如果您有模式文档的模式的本地副本,您当然可以指向它,但同样可以指向 W3C 服务器上的副本。所以:不,您“不需要”拥有本地副本。不过,您可能很想这样做:W3C 的服务器在每次解析 XML 文档时都试图取消引用 DTD 和模式文档的软件受到了打击,而 W3C 的系统管理员通过使他们的服务器对此类请求的响应非常缓慢来做出响应。一个本地副本如果因此可能更方便,即使它在任何意义上都不是必需的。

    1(b)。当我尝试保存在 w3.org/2001/XMLSchema 中找到的架构的本地副本时,我收到该架构的验证错误,理由是“xs:occurs”已被声明。如果我注释掉该属性组,我会在整个过程中遇到类似的错误。

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

    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="w3.org/2001/XMLSchema"; (我怀疑这会消除重复的定义错误,我得到另一个错误,指出“元素'xs:schema'没有声明名为'xmlns:hfp'的属性”你或任何人能告诉我我是什么这里做错了吗?

    您的文档几乎在每个元素上都使用了命名空间前缀 xs。您确实想删除该前缀的命名空间绑定。

    使 XSD 验证器对模式文档使用修改后的模式形式,就其方式而言,是使用 XSD 的一个高级主题。 (任何时候你使用语言 L 来描述并可能修改语言 L,很容易让自己陷入目标语言和元语言之间的混淆。询问离你最近的大师他们花了多长时间来理解他们曾经的第一个元循环解释器研究过。)

    如果您正处于使用 XML 和 XSD 的阶段,您对删除其中一个架构文档中的命名空间声明可能产生的影响有任何疑问,那么您可能会发现您已经完成了一项非常具有挑战性的任务.我不会说你不应该花时间在上面,原因与我不会告诉青少年不要花时间重建引擎的原因大致相同。这可能很有趣,你可能会学到很多东西。但是,如果您不将其作为目的本身,您需要知道它不会快速或简单。您不太可能通过以这种方式摆弄命名空间声明来使其工作。 (在这种情况下,我建议你阅读the story of Tom Knight and the Lisp Machine。)

    【讨论】:

    • 好的。在我尝试实施您的建议时出现了一些问题: 1. 我的编辑器使用的 xsd 验证器仅与 xsd 1.0 版兼容。尽管如此,根据您上面的示例,我已经尝试使用 1.0 来实现我的目标。在此过程中,我遇到了以下问题/疑问:
    • 1(a)。我仍然需要用于验证架构文档的架构的本地副本,对吗? (在您的情况下:sfsd-11.xsd,在我的情况下:在w3.org/2001/XMLSchema 找到的架构?[命名但我选择命名它?)?
    • 1(b)。当我尝试保存在w3.org/2001/XMLSchema 找到的架构的本地副本时,我收到该架构的验证错误,理由是“xs:occurs”已被声明。如果我注释掉那个属性组,我会在整个过程中遇到类似的错误。
    • 1 (c)。请注意,我在本地保存的架构顶部包含了 XMLSchema.dtd 标头(并在本地保存了 dtd)本地架构的属性: "w3.org/2001/XMLSchema" blockDefault="#all" elementFormDefault="qualified" 版本="1.0" xmlns:xs="w3.org/2001/XMLSchema" xml:lang="EN" xmlns:hfp="w3.org/2001/XMLSchema-hasFacetAndProperty" finalDefault=" " attributeFormDefault="unqualified">
    • 1 (c)(续)当我删除 xmlns:xs="w3.org/2001/XMLSchema" 时(我怀疑这会消除重复的定义错误,我收到另一个错误,指出“元素 'xs :schema' 没有声明名为 'xmlns:hfp' 的属性" 你或任何人能告诉我我在这里做错了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2019-05-14
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多