3

我的目标是对我的 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>
4

1 回答 1

4

好问题!

应该提出几点:

  • 首先,我猜您已经知道(尽管该问题的某些读者和该答案可能不知道),您的架构文档 1 已经是合法的。因此,您无需修改​​架构文档的架构以使其合法。但是,如果我对您的理解正确,那么您不仅希望它有效;您希望它的变体在没有 xs:documentation 元素或没有 ds:add 和 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 架构文档的架构;模式文档如下所示,我希望这些评论能够合理地说明正在发生的事情。如果您只能访问 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(一)。我仍然需要用于验证架构文档的架构的本地副本,对吗?(在您的情况下: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 的阶段,并且对删除其中一个模式文档中的名称空间声明可能产生的影响有任何疑问,那么您可能会发现您已经完成了一项非常具有挑战性的任务。我不会说你不应该花时间在上面,原因与我不会告诉青少年不要花时间重建引擎的原因大致相同。这可能很有趣,你可能会学到很多东西。但是,如果您不将其作为目的本身,您需要知道它不会快速或简单。您不太可能通过以这种方式摆弄命名空间声明来使其工作。(在这种情况下,我建议你阅读Tom Knight 和 Lisp 机器的故事。)

于 2013-06-28T02:45:29.160 回答