views:

277

answers:

1

The XML I'm trying to validate is as follows:

<root>
    <element attribute="foo">
        <bar/>
    </element>
    <element attribute="hello">
        <world/>
    </element>
</root>

How can this be validated using a Schema?

Note:

element can only contain bar when attribute="foo".

element can only contain world when attribute="hello"

+4  A: 

You can't do this in XML Schema 1.0. In XML Schema 1.1 you will be able to use the <xs:assert> element to do it, but I'm guessing you want something that you can use now.

You can use Schematron as a second layer of validation that will allow you to test arbitrary XPath assertions about your XML document. There's a fairly old article about embedding Schematron in XSD that you might find helpful.

You'd do something like:

<rule context="element">
  <report test="@attribute = 'foo' and *[not(self::bar)]">
    This element's attribute is 'foo' but it holds an element that isn't a bar.
  </report>
  <report test="@attribute = 'hello' and *[not(self::world)]">
    This element's attribute is 'hello' but it holds an element that isn't a world.
  </report>
</rule>

Or of course you can switch to RELAX NG, which does this in its sleep:

<element name="element">
  <choice>
    <group>
      <attribute name="attribute"><value>foo</value></attribute>
      <element name="bar"><empty /></element>
    </group>
    <group>
      <attribute name="attribute"><value>hello</value></attribute>
      <element name="world"><empty /></element>
    </group>
  </choice>
</element>
JeniT