xsd:choice 内元素的 minOccurs 和 maxOccurs

minOccurs and maxOccurs on elements inside xsd:choice

我有一个根元素 <a> 及其子元素 <b>, <c>, <d>

这是我需要的:

例如:

<a>
    <c />
    <b />
    <c />
    <d /> 
</a>

这是我的 XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified"
           attributeFormDefault="unqualified">
  <xs:element name="a">
    <xs:complexType>
      <xs:choice>
        <xs:element name="b" />
        <xs:element name="c" minOccurs="1" maxOccurs="unbounded"/>
        <xs:element name="d" minOccurs="0" maxOccurs="1"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

但是xs:element中的minOccursmaxOccurs可能不起作用。当我 运行 这个例子时,我得到一个错误:

Element <b> is not allowed at this location under element <a>.

我该如何解决这个问题?

这是您的 XSD 所说的:a 中,您可以选择以下选项之一:

  1. 单个 b 元素。
  2. 一个或多个 c 个元素。
  3. 零个或一个 d 个元素。

您的 XML 选择选项 #2。它没有第二个选择,当解析器遇到 b 元素时,它会正确报告违规。

您可能认为可以通过授予多项选择来解决此问题:

  <xs:choice maxOccurs="unbounded">

现在会说:a中你可以重复选择以下选项之一:

  1. 单个 b 元素。
  2. 一个或多个 c 个元素。
  3. 零个或一个 d 个元素。

您的 XML 现在会选择选项 #2,然后选择选项 #1,然后选择选项 #2,然后选择选项 #3,然后声明您的 XML 有效。成功了吗?

不,不是,例如,如果您希望确保 只有一个 b 元素子元素,因为选择本身是重复的,并且选项 #1 可以重复选择,每次允许单个 b 元素,但总的来说,有效地允许多个 b 元素。

因此,xsd:choice,事实上,XSD 1.0 通常不能用来表示您的约束。

您的选择? 在 XSD 之外的代码中检查此约束,或使用 XSD 1.1 的 xsd:assert:

XSD 1.1 解决方案

<?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="a">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="b" />
        <xs:element name="c"/>
        <xs:element name="d"/>
      </xs:choice>
      <xs:assert test="count(b) = 1 and count(c) > 1 and count(d) >= 0"/>
    </xs:complexType>
  </xs:element>
</xs:schema>