I'm trying to create a schema for a <property>
element which must have a <key>
sub-element, and one of <val>
, <shell>
or <perl>
and an optional <os>
or <condition>
, and the order of the sub-elements doesn't matter.
我正在尝试为一个必须具有
Here are some sample for valid <property>
elements:
以下是有效
<property>
<key>A</key>
<val>b</val>
</property>
<property>
<key>A</key>
<val>b</val>
<os>Windows</os>
</property>
<property>
<condition>a == 1</condition>
<key>A</key>
<perl>1+1</perl>
<os>unix</os>
</property>
Ideally, I thought of using <xs:all>
for this:
理想情况下,我想使用
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:choice>
<xs:element name="val" type="xs:string" />
<xs:element name="perl" type="xs:string" />
<xs:element name="shell" type="xs:string" />
</xs:choice>
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
But I found out that <xs:all>
can contain only <xs:element>
and not <xs:choice>
. Can someone explain why is it?
但我发现
More importantly, can someone provide a way to validate such a <property>
element?
更重要的是,有人能提供一种验证此类
I can put the three elements - <val>
, <perl>
and <shell>
- as optional elements in the <xs:all>
, but I want the schema to validate that one and only one of the three exists in the element. Can this be done?
我可以将三个元素——
2 个解决方案
#1
22
I think this is a bit better, as the "choice" is now it's own element (typeFacet), but cannot be used directly as it is abstract.
我认为这更好一点,因为“选择”现在是它自己的元素(typeFacet),但是不能直接使用,因为它是抽象的。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="typeFacet" />
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="typeFacet" abstract="true" />
<xs:element name="val" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="perl" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="shell" type="xs:string" substitutionGroup="typeFacet" />
</xs:schema>
#2
6
Based on newt's comment about using substitution groups for the choice (tested with xmllint):
根据newt关于使用替代组进行选择的评论(使用xmllint进行测试):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="val"/>
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="val" type="xs:string"/>
<xs:element name="perl" type="xs:string" substitutionGroup="val" />
<xs:element name="shell" type="xs:string" substitutionGroup="val" />
</xs:schema>
#1
22
I think this is a bit better, as the "choice" is now it's own element (typeFacet), but cannot be used directly as it is abstract.
我认为这更好一点,因为“选择”现在是它自己的元素(typeFacet),但是不能直接使用,因为它是抽象的。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="typeFacet" />
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="typeFacet" abstract="true" />
<xs:element name="val" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="perl" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="shell" type="xs:string" substitutionGroup="typeFacet" />
</xs:schema>
#2
6
Based on newt's comment about using substitution groups for the choice (tested with xmllint):
根据newt关于使用替代组进行选择的评论(使用xmllint进行测试):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="val"/>
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="val" type="xs:string"/>
<xs:element name="perl" type="xs:string" substitutionGroup="val" />
<xs:element name="shell" type="xs:string" substitutionGroup="val" />
</xs:schema>