Another XSD question - how can I achieve that the following XML elements are both valid:
<some-element>
<type>1</type>
<a>...</a>
</some-element>
<some-element>
<type>2</type>
<b>...</b>
</some-element>
The sub-elements (either <a>
or <b>
) should depend on the content of <type>
(could also be an attribute). It would be so simple in RelaxNG - but RelaxNG doesn't support key integrity :(
Is there a way to implement this in XSD?
Note: XML schema version 1.1 supports <xs:alternative>
, which might be a solution, but afaik no reference implementation (e.g. libxml2) supports this yet. So I'm searching for workarounds. The only way I've come up with is:
<type>1</type>
<some-element type="1">
<!-- simple <xs:choice> between <a> and <b> goes here -->
<a>...</a>
</some-element>
<!-- and now create a keyref between <type> and @type -->
The best solution is to remove the <type/>
element and only have a xs:choice
for <a/>
and <b/>
and let the application consuming the xml sort out the type.
Another solution might be to have a xs:choice
for <a/>
and <b/>
use an xslt script to do a validation of the <type/>
element in relation to <a/>
and <b/>
.
First validate the xml against the xmlschema then use the xslt to do a transformation on it, if the result of the transform is empty string it is valid otherwise show the resulting string as an error message.
Something like this...
XmlSchema:
<xs:element name="some-element">
<xs:complexType>
<xs:sequence>
<xs:element name="type" type="xs:integer" />
<xs:choice>
<xs:element name="a" type="xs:string" />
<xs:element name="b" type="xs:string" />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:demo="uri:demo:namespace">
<xsl:output method="text" />
<xsl:template match="/demo:some-element">
<xsl:if test="type = 1 and not(demo:a)">
When type equals 1 element a is requred.
</xsl:if>
<xsl:if test="type = 2 and not(demo:b)">
When type equals 2 element b is requred.
</xsl:if>
</xsl:template>
</xsl:stylesheet>
No, XML Schema 1.0 cannot do this.