14

我试图使两个 XML 属性互斥。如何创建 XSD 模式来捕获这种场景?

我想要其中之一

<elem value="1" />
<elem ref="something else" />

但不是

<elem value="1" ref="something else" />
4

6 回答 6

9

您不能使用属性,但可以使用子元素...

<element name="elem">
    <complexType>
        <choice>
            <element name="value"/>
            <element name="ref"/>
        </choice>
    </complexType>
</element>

这样你就可以拥有...

<elem>
    <value>1</value>
</elem>

或者...

<elem>
    <rel>something else</rel>
</elem>
于 2008-12-22T16:57:20.267 回答
7

不幸的是,AFAIK 你不能用 XML Schema 做到这一点,我自己也遇到了同样的问题。

我已经看到它建议如果您需要两者:

<elem type="xxx"> 
<elem ref="yyy">

那么<elem>本身应该分为两种类型,因为它们显然具有不同的属性...

于 2008-12-22T16:46:42.627 回答
5

由于在 Alnitak 的回答中提到了RelaxNG ,这里有一个使用 RelaxNG 的解决方案(一种在大多数情况下比 W3C Schema 更好的语言)。请注意 elem 定义中的 OR (|):

start = document
document = element document {elem+}
elem = element elem {ref | value}
ref = attribute ref {text}
value = attribute value {xsd:integer}

如果我有这个 XML 文件:

<document>
    <elem value="1" />
    <elem ref="something else" />
</document>

它被rnvxmlint接受:

 % rnv attributes-exclusive.rnc attributes-exclusive.xml             
 attributes-exclusive.xml

 % xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml 
 attributes-exclusive.xml validates

如果我在 XML 文件中添加:

<elem value="1" ref="something else" />

我得到了我想要的验证错误(请注意错误消息不是最理想的):

% rnv attributes-exclusive.rnc attributes-exclusive.xml    
attributes-exclusive.xml
attributes-exclusive.xml:4:0: error: attribute ^ref not allowed
required:
       after

% xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml
attributes-exclusive.xml:4: element elem: Relax-NG validity error : Invalid attribute value for element elem
attributes-exclusive.xml fails to validate
于 2008-12-23T08:48:48.520 回答
3

实际上,可以通过 xs:unique 或 xs:key 使用身份约束在 XSD 1.0 中定义它。您选择哪一个取决于如何处理没有这两个属性中的任何一个的元素:它们对 xs:unique 有效,但对 xs:key 无效。下面的代码示例包含两种变体;确保删除其中一个,否则“更严格”的 xs:key 优先于 xs:unique,即需要两个属性之一。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="container">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="elem" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="value" use="optional"/>
            <xs:attribute name="ref" use="optional"/>
          </xs:complexType>
          <!-- Note: Use either xs:unique or xs:key -->
          <xs:unique name="attrsExclusiveOptional">
            <xs:annotation>
              <xs:documentation>Ensure that @value and @ref cannot occur simultaneously.
Both may be omitted.</xs:documentation>
            </xs:annotation>
            <xs:selector xpath="."/>
            <xs:field xpath="@value | @ref"/>
          </xs:unique>
          <xs:key name="attrsExclusiveRequired">
            <xs:annotation>
              <xs:documentation>Ensure that @value and @ref cannot occur simultaneously.
One of them is required.</xs:documentation>
            </xs:annotation>
            <xs:selector xpath="."/>
            <xs:field xpath="@value | @ref"/>
          </xs:key>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

这将验证以下 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="schema.xsd">
  <!-- Shall pass: -->
  <elem value="1" />
  <elem ref="something else" />

  <!-- Passes for xs:unique, fails for xs:key: -->
  <elem />

  <!-- Shall fail: -->
  <elem value="1" ref="something else" />
</container>
于 2017-11-08T13:57:37.500 回答
2

XSD 对此有抽象类型:http ://www.tek-tips.com/viewthread.cfm?qid= 1364846(参见 tsuji 的帖子)

基本上,您为手头的元素提供一个abstract、复杂的类型,并在其中定义它的通用属性,对于所有不同的用例,这些属性完全相同(您的示例不需要)。

然后创建 2 个(或更多)额外的复杂类型来扩展我刚才提到的抽象类型。在这些新类型中,您可以在每个用例之间定义不同的属性集。XSD 部分就是这样。

最后,您需要将 XSItype属性添加到模式实例文档中的结果元素。因此,要有效,该元素现在必须具有一组属性或另一组属性。

不是直截了当,而是灵活,众所周知:越灵活,事情就越困难。

于 2013-01-26T16:56:46.837 回答
1

对于稍后阅读此内容的读者,请注意该问题可以在 XSD 1.1 中使用“条件类型分配”或断言来解决。

于 2014-12-30T00:38:22.760 回答