xsd:choice 内元素的 minOccurs 和 maxOccurs
minOccurs and maxOccurs on elements inside xsd:choice
我有一个根元素 <a>
及其子元素 <b>, <c>, <d>
这是我需要的:
- 子元素可以任何顺序出现
- 只有 1 个
<b>
- 1个以上
<c>
- 0 或 1
<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
中的minOccurs
和maxOccurs
可能不起作用。当我 运行 这个例子时,我得到一个错误:
Element <b>
is not allowed at this location under element <a>
.
我该如何解决这个问题?
这是您的 XSD 所说的: 在 a
中,您可以选择以下选项之一:
- 单个
b
元素。
- 一个或多个
c
个元素。
- 零个或一个
d
个元素。
您的 XML 选择选项 #2。它没有第二个选择,当解析器遇到 b
元素时,它会正确报告违规。
您可能认为可以通过授予多项选择来解决此问题:
<xs:choice maxOccurs="unbounded">
现在会说:在a
中你可以重复选择以下选项之一:
- 单个
b
元素。
- 一个或多个
c
个元素。
- 零个或一个
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>
我有一个根元素 <a>
及其子元素 <b>, <c>, <d>
这是我需要的:
- 子元素可以任何顺序出现
- 只有 1 个
<b>
- 1个以上
<c>
- 0 或 1
<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
中的minOccurs
和maxOccurs
可能不起作用。当我 运行 这个例子时,我得到一个错误:
Element
<b>
is not allowed at this location under element<a>
.
我该如何解决这个问题?
这是您的 XSD 所说的: 在 a
中,您可以选择以下选项之一:
- 单个
b
元素。 - 一个或多个
c
个元素。 - 零个或一个
d
个元素。
您的 XML 选择选项 #2。它没有第二个选择,当解析器遇到 b
元素时,它会正确报告违规。
您可能认为可以通过授予多项选择来解决此问题:
<xs:choice maxOccurs="unbounded">
现在会说:在a
中你可以重复选择以下选项之一:
- 单个
b
元素。 - 一个或多个
c
个元素。 - 零个或一个
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>