我有一个XML Schema,它定义了一个complexType,如下所示:
<xs:complexType name="CompType">
<xs:sequence>
<xs:element name="A" type="TypeA" minOccurs="0" maxOccurs="1"/>
<xs:choice minOccurs="1" maxOccurs="12">
<xs:element name="B" type="TypeB"/>
<xs:element name="C" type="TypeC"/>
<xs:element name="D" type="TypeD"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
我需要它来验证一个XML元素,该元素最多可以包含12个“普通”子元素(normal = TypeB,TypeC或TypeD),但可能还有一个TypeA的“特殊”子元素。
因为它有效,但我不想限制“特殊”子元素始终是第一个。换句话说,我希望能够执行类似下面的操作,并增加限制,即只能有一个TypeA子元素,并且不超过12个“普通”子元素。
<xs:complexType name="CompType">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="13">
<xs:element name="A" type="TypeA"/>
<xs:element name="B" type="TypeB"/>
<xs:element name="C" type="TypeC"/>
<xs:element name="D" type="TypeD"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
这一切都可能吗?如果是,有人可以指出如何或者至少指出我正确的方向吗?
答案 0 :(得分:1)
Unique Particle Attribution(UPA)限制将阻碍为 XSD 1.0 实现此目标的任何巧妙尝试。
即使你想要0或更多B,C或D并且任意顺序只有0或1 A的情况也是如此。考虑:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">
<xs:element name="X" type="CompType"/>
<xs:complexType name="CompType">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="B"/>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:choice>
<xs:element name="A" minOccurs="0"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="B"/>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:schema>
验证需要预先查看多个标签,从而违反UPA。 Xerces会表达不满:
cos-nonambig: B and B (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
问题仍然存在于maxOccurs = 12场景中,除非你想疯狂并列举所有可能性。
如果您可以使用 XSD 1.1 ,则可以使用其xs:assert
设施。 (未测试:)
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.1">
<xs:element name="X" type="CompType"/>
<xs:complexType name="CompType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="A"/>
<xs:element name="B"/>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:choice>
<xs:assert test="(count(./A) le 1) and (count(./A) + count(./B) + count(./C) + count(./D) le 13)"/>
</xs:complexType>
</xs:schema>