【问题标题】:How to declare an xs:element with two different sets of attributes?如何声明具有两组不同属性的 xs:element?
【发布时间】:2019-02-10 14:57:44
【问题描述】:

我的新 XML 私有语言包含元素 <figure>,代表插图(图像 + 标题)。

每当插图引用本地数据库中的某些图像时,我只想输入

<figure id="9809" width="full" />

识别图像编号 9809 及其相关标题。

另一方面,如果图像来自外部,我将需要稍微不同的语法:

<figure href="https://some-url-here" width="full">Some ad hoc catpion</figure>

到目前为止,我已经声明了一个结合了这两种行为的元素,如下所示:

  <!-- Figures -->
  <xs:simpleType name="FigureWidthEnum">
    <xs:restriction base="xs:token">
      <xs:enumeration value="center" />
      <xs:enumeration value="half" />
      <xs:enumeration value="full" />
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="figure">
    <xs:complexType mixed="true">
      <xs:complexContent>
        <xs:extension base="Inline">
          <xs:attribute name="href" type="URI" />
          <xs:attribute name="id" type="xs:nonNegativeInteger" />
          <xs:attribute name="width" type="FigureWidthEnum" default="full" />
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>

它工作得很好,但是一个新的编辑器可能会弄乱这 3 个属性并键入不可能的东西,我不想那么容易通过 Schema Validator。例如:

<figure id="9809" width="full" href="https://some-unexpected-url">Some unexpected caption that should not be here</figure>

我想为&lt;figure&gt; 有两个完全独立的sintaxes,好像我可以用相同的名称声明这两个元素:

  <xs:element name="figure">
    <xs:complexType mixed="true">
      <xs:complexContent>
        <xs:extension base="Inline">
          <xs:attribute name="href" type="URI" />
          <xs:attribute name="width" type="FigureWidthEnum" default="full" />
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>

  <xs:element name="figure">
    <xs:complexType>
      <xs:attribute name="id" type="xs:nonNegativeInteger" />
      <xs:attribute name="width" type="FigureWidthEnum" default="full" />
    </xs:complexType>
  </xs:element>

事实上这是不可能的。

可以通过某种方式完成吗?

【问题讨论】:

    标签: xsd schema


    【解决方案1】:

    是的,可以使用 XSD 1.1,它提供了专门用于此类要求的 &lt;xs:alternative&gt; 元素。这是我设计的一个完整的 XML 模式,可以完全按照您的需要进行验证:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
               vc:minVersion="1.1">
    
      <!-- Figures -->
      <xs:simpleType name="FigureWidthEnum">
      <xs:restriction base="xs:token">
        <xs:enumeration value="center" />
          <xs:enumeration value="half" />
          <xs:enumeration value="full" />
        </xs:restriction>
      </xs:simpleType>
    
      <!-- stub definition -->
      <xs:complexType name="Inline"/>
    
      <!-- 'figure' element is declared once, but its type has two alternatives -->
      <xs:element name="figure">
    
        <!-- The first alternative is selected, when the condition specified
         in 'test' attribute is true. The condition must be a boolean XPath
         expression. The '@id' returns the value of 'id' attribute. However,
         when converted to boolean, it indicates whether 'id' attribute is
         specified at all. The anonymous complexType inside <xs:alternative>
         provides the element type valid for this case.
        -->
        <xs:alternative test="@id">
          <xs:complexType>
            <xs:attribute name="id" type="xs:nonNegativeInteger" />
            <xs:attribute name="width" type="FigureWidthEnum" default="full" />
          </xs:complexType>
        </xs:alternative>
    
        <!-- The second alternative has no 'test' attribute. That means, it must
         be selected by default, when all other alternatives (with a specified
         test condition) do not pass. Here, the anonymous complexType inside
         <xs:alternative> defines the element type in case of reference:
         when 'href' is present.
        -->
        <xs:alternative>
          <xs:complexType mixed="true">
            <xs:complexContent>
              <xs:extension base="Inline">
                <xs:attribute name="href" type="xs:anyURI" />
                <xs:attribute name="width" type="FigureWidthEnum" default="full" />
              </xs:extension>
            </xs:complexContent>
          </xs:complexType>
        </xs:alternative>
      </xs:element>
    
      <!-- this element is defined just to test the whole schema in XML below -->
      <xs:element name="figures">
        <xs:complexType>
          <xs:sequence>    
            <xs:element ref="figure" minOccurs="0" maxOccurs="unbounded"/>
          </xs:sequence>    
        </xs:complexType>
      </xs:element>
    
    </xs:schema>
    

    此架构验证的完整 XML 文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <figures>
    
      <!-- passes validation -->
      <figure id="9809" width="full" />
    
      <!-- passes validation -->
      <figure width="full" href="https://some-unexpected-url">Some ad hoc caption</figure>
    
      <!-- does not pass the validation -->
      <figure id="9809" width="full" href="https://some-unexpected-url">
        Some unexpected caption that should not be here
      </figure>
    
    </figures>
    

    使用 Apache Xerces 2.11.0(支持 XSD 1.1)完成验证。


    促销插件。这些链接对于那些使用 XML 模式和 WSDL 的人来说可能会很有趣:FlexDoc/XML XSDDocWSDLDoc – 高性能通用 XML 模式/带图表的 WSDL 文档生成器

    【讨论】:

    • 哇@ColdFusion !太感谢了。我尝试使用 没有成功,因为我不知道
    • 不幸的是,从 XSD 1.0 升级到 XSD 1.1。需要不同的验证 Java 类(我使用的是 java.xml)。我测试了你的 XSD 块并且 根本无法识别。为了读者在 Java 中实现此解决方案的利益,我了解到必须改用 Xerces。看看stackoverflow.com/questions/20807066/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    相关资源
    最近更新 更多