views:

988

answers:

3

I'm trying to make two XML attributes to be mutually exclusive. How can one create an XSD schema to capture this kind of scenario?

I would like to have one of these

<elem value="1" />
<elem ref="something else" />

but not

<elem value="1" ref="something else" />
+4  A: 

Unfortunately AFAIK you can't do that with XML Schema, I've had the same problem myself.

I've seen it suggested that if you need both of:

<elem type="xxx"> 
<elem ref="yyy">

then <elem> itself should be split into two types, since they've clearly got different attributes...

Alnitak
Is there any other schema language/style (other than XSD) where it would be possible?
Filip
@Filip: The only other schema language I know of is relaxNG, but I know nothing about it.
Draemon
There's always xsd:annotation "Hey, don't include x and y on z".
jmucchiello
I just posted an answer with a RelaxNG solution.
bortzmeyer
+1  A: 

You can't do with attributes, but you can with child elements...

<element name="elem">
    <complexType>
     <choice>
      <element name="value"/>
      <element name="ref"/>
     </choice>
    </complexType>
</element>

This way you can have...

<elem>
    <value>1</value>
</elem>

or...

<elem>
    <rel>something else</rel>
</elem>
Daniel Silveira
+2  A: 

Since RelaxNG was mentioned in Alnitak's answer, here is a solution with RelaxNG (a language which is, in most cases, better than W3C Schema). Do note the OR (|) in the definition of elem:

start = document
document = element document {elem+}
elem = element elem {ref | value}
ref = attribute ref {text}
value = attribute value {xsd:integer}

If I have this XML file:

<document>
    <elem value="1" />
    <elem ref="something else" />
</document>

It is accepted by rnv and xmlint:

 % rnv attributes-exclusive.rnc attributes-exclusive.xml             
 attributes-exclusive.xml

 % xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml 
 attributes-exclusive.xml validates

If I add in the XML file:

<elem value="1" ref="something else" />

I get validation errors, as I want (do note that the error messages are suboptimal):

% rnv attributes-exclusive.rnc attributes-exclusive.xml    
attributes-exclusive.xml
attributes-exclusive.xml:4:0: error: attribute ^ref not allowed
required:
       after

% xmllint --noout --relaxng attributes-exclusive.rng attributes-exclusive.xml
attributes-exclusive.xml:4: element elem: Relax-NG validity error : Invalid attribute value for element elem
attributes-exclusive.xml fails to validate
bortzmeyer