simple - Esquema XML: ¿Por qué<xs: all> no puede tener<choice> hijos? ¿Y cómo puede ser pasado por alto?
xsd attribute example (2)
Estoy intentando crear un esquema para un elemento <property>
que debe tener un subelemento <key>
y uno de <val>
, <shell>
o <perl>
y un <os>
o <condition>
opcional, y el orden de los subelementos no importa.
Aquí hay algunos ejemplos de elementos <property>
válidos:
<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>
Idealmente, pensé en usar <xs:all>
para esto:
<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>
Pero descubrí que <xs:all>
solo puede contener <xs:element>
y no <xs:choice>
. ¿Alguien puede explicar por qué es?
Más importante aún, ¿puede alguien proporcionar una manera de validar dicho elemento <property>
?
Puedo poner los tres elementos - <val>
, <perl>
y <shell>
- como elementos opcionales en <xs:all>
, pero quiero que el esquema valide que uno y solo uno de los tres existen en el elemento. Se puede hacer esto?
Basado en el comentario de newt sobre el uso de grupos de sustitución para la elección (probado con 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>
Creo que esto es un poco mejor, ya que la "elección" es ahora su propio elemento (typeFacet), pero no se puede usar directamente ya que es abstracto.
<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>