Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

[Schema]How to define the content of a node, based on its descendants?

Basically, the subject says it all:
How to define the content of a node, based on it's descendants?

In detail... I'm making a schema for an XSLT reference. The basic structure of the XML file is
<reference>
<elements>
<v1>
<element>...</element>
...
</v1>
<v2>
<element>...</element>
...
</v2>
<exslt>
<module name="...">
<element>...</element>
...
</module>
...
</exslt>
</elements>
<functions>
<xslt>
<v1>
<function>...</function>
...
</v1>
<v2>
<function>...</function>
...
</v2>
<exslt>
<module name="...">
<function>...</function>
...
</module>
...
</exslt>
</xslt>
<xpath>
<v1>
<function>...</function>
...
</v1>
<v2>
<function>...</function>
...
</v2>
</xpath>
</functions>
And the Schema I have for it so far is:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="reference">
<xs:complexType>
<xs:sequence>
<xs:element ref="elements"/>
<xs:element ref="functions"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elements">
<xs:complexType>
<xs:sequence>
<xs:element ref="v1"/>
<xs:element ref="v2"/>
<xs:element ref="exslt"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="functions">
<xs:complexType>
<xs:sequence>
<xs:element ref="xslt"/>
<xs:element ref="xpath"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="xslt">
<xs:complexType>
<xs:sequence>
<xs:element ref="v1"/>
<xs:element ref="v2"/>
<xs:element ref="exslt"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="xpath">
<xs:complexType>
<xs:sequence>
<xs:element ref="v1"/>
<xs:element ref="v2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="v1">
<xs:complexType>
<xs:choice>
<xs:element maxOccurs="unbounded" ref="element"/>
<xs:element maxOccurs="unbounded" ref="function"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="v2">
<xs:complexType>
<xs:choice>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="function"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="element"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="exslt">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="module"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="function">
<xs:complexType>
<xs:group ref="model"/>
</xs:complexType>
</xs:element>
<xs:element name="element">
<xs:complexType>
<xs:group ref="model"/>
</xs:complexType>
</xs:element>
<xs:element name="module">
<xs:complexType>
<xs:choice>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="element"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="function"/>
</xs:choice>
<xs:attribute name="name" use="required"/>
</xs:complexType>
</xs:element>
<xs:group name="model" id="model">
<xs:sequence>
<xs:element name="name" type="xs:NCName"/>
<xs:element name="description">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="code"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="status" type="xs:NCName" minOccurs="0"/>
<xs:element name="note" minOccurs="0" maxOccurs="unbounded">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="code"/>
</xs:sequence>
<xs:attribute name="for" type="xs:NCName"/>
<xs:attribute name="on" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:element name="code" type="xs:NMTOKEN"/>
</xs:schema>
As you can see, I'm using <xs:choise> in order to choose to either have <element> or <function> as only childs of whatever references them. This method makes my file valid, but it also makes it valid, if there was a <function> element where only <element> should be acceptable and vise-versa. For example (I have used XPath expression for the sake of lesser space):
/reference/element/v1/function
or
/reference/functions/exslt/module/element
I could declare the <v1>, <v2> and <module> several times over, calling the appropriate child, but I don't want this. Is there a way I could define each of those elements once and choose their childs based on whatever their descendants were?
[6235 byte] By [boen_robot] at [2007-11-11 9:41:57]