如何在 XSD 中定义互斥属性?

Posted

技术标签:

【中文标题】如何在 XSD 中定义互斥属性?【英文标题】:How to define mutually exclusive attributes in XSD? 【发布时间】:2016-02-18 07:48:27 【问题描述】:

###首先是代码片段...

<tag name="default" abc="10" def="20"> <!-- not valid, abc and def should be mutually exclusive -->

<tag name="default1" abc="10"> <!-- valid -->

<tag name="default2" def="20"> <!-- valid -->

###我想做什么...

我可以在我的XSD 中添加什么,以使@abc@def 不能作为同一元素上的属性共存?

如果它们共存于同一个元素上,那么验证就会失败?

【问题讨论】:

你没有说&lt;tag name="default3"/&gt;是否应该是有效的(即当两个属性都不存在时)。 是的,我想那是无效的,它需要其中之一 @ycomp 看我的回答。 【参考方案1】:

根据https://www.w3.org/TR/xmlschema-1/#Selector 页面,我猜想用 xs:key 来处理属性之间的互斥量在其他解决方案中是行不通的。

它说,“在标记化时,总是返回最长的标记。”

【讨论】:

【参考方案2】:

XSD 1.0

可以使用xs:key 巧妙地完成。见@Kachna's answer。

请注意,如果 xs:key 中的多个选定值失败,某些解析器可能会允许这两个属性。过去至少有 one known case 发生过这种情况。

XSD 1.1

可以使用xs:assert:

<?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">
  <xs:element name="tag">
    <xs:complexType>
      <xs:sequence/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="abc" use="optional" type="xs:integer"/>      
      <xs:attribute name="def" use="optional" type="xs:integer"/>
      <xs:assert test="(@abc and not(@def)) or (not(@abc) and @def)"/>      
    </xs:complexType>
  </xs:element>
</xs:schema>

【讨论】:

XSD 1.1 中的另一种方法是使用条件类型赋值:有一种类型允许 abc 但不允许 def,第二种类型允许 def 但不允许 abc,并使用 xs:alternative 在它们之间进行选择。 【参考方案3】:

使用 XSD 1.0,您可以使用xs:keyelement。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="tag">
    <xs:complexType>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="abc"  type="xs:integer"/>      
        <xs:attribute name="def"  type="xs:integer"/>
     </xs:complexType>
    <xs:key name="attributeKey">
        <xs:selector xpath="."/>
        <xs:field xpath="@abc|@def"/>
    </xs:key>
</xs:element>   

编辑: 如果两个属性都存在(即使具有不同的值),这将创建两个键,因此 XML 验证将失败。另一方面,&lt;xs: key&gt; 要求为元素定义一个键,因此必须存在两个属性之一。

以下 XML 文档在使用上述 XSD 时无效。 (我使用的是 oXygen 17.0):

<tag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="stack3.xsd" name="" abc="12" def="13"/>

错误:

cvc-identity-constraint.3: Field "./@abc|./@def" of identity constraint "attributeKey" matches more than one value within the scope of its selector; fields must match unique values

【讨论】:

在 Visual Studio 2015 中,该错误可能具有误导性:The field 'def' is expecting at the most one value.

以上是关于如何在 XSD 中定义互斥属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 XSD 复杂类型定义中混合扩展和限制

如何在XML / XSD中定义整数范围?

XSD:如何重新定义基本模式的标签

为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?

如何在本地使用 XSD 验证 XML 文件?

如何添加xs:发生属性组到我的元素声明?