Re: Multiple Types in XSD?

Hi Lee,

> Section 2.2.3 ("Naming Conflicts") of XML Schema Part 0: Primer
> seems to suggest to me that the only way I can define an element as
> either one thing or another is by using different namespaces.
>
> Am I correct in thinking this or is there a more elegant solution?

There is a more elegant solution, although it does involve changing
the XML instances (but then, so would using different namespaces).

The content and attributes of an element are its type, so what you're
asking here is about saying that an element can either be one type or
another type.

You can do this by creating two, related, complex types; with your
example, since the name element has to come first, I think that
easiest way is to create an abstract type that allows both a name
attribute and a name child element, and then restrict it to make the
two types that you actually want, as follows:

<xs:complexType name="abstractListType" abstract="true">
  <xs:sequence>
    <xs:element name="name" type="xs:string" minOccurs="0" />
    <xs:element name="data" type="xs:string" />
  </xs:sequence>
  <xs:attribute name="name" type="xs:string" />
</xs:complexType>

<xs:complexType name="attributeListType">
  <xs:complexContent>
    <xs:restriction base="generalListType">
      <xs:sequence>
        <xs:element name="data" type="xs:string" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="required" />
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="elementListType">
  <xs:complexContent>
    <xs:restriction base="generalListType">
      <xs:sequence>
        <xs:element name="name" type="xs:string" />
        <xs:element name="data" type="xs:string" />
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="prohibited" />
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

When you define the list element, give it the abstract type as its
type:

<xs:element name="list" type="abstractListType" />

Now, the list element in the instance cannot actually be of the
abstract list type because it's abstract, so it must be of one of the
derived types. For each list element in the instance, you have to
indicate the type of list it is, using the xsi:type attribute, for
example:

        <list xsi:type="elementListType">
                <name>foo</name>
                <data>bar</data>
        </list>
or
        <list xsi:type="attributeListType" name="foo">
                <data>bar</data>
        </list>

You could do a similar thing, but changing the names of the elements,
using substitution groups, but I imagine that that's not an option
(since if they could have different names there wouldn't be this
problem anyway).
        
If you can't change the instances by adding xsi:type attributes, then
I don't think that there's a way to articulate the constraint using
XML Schema. In that case, you should make the abstract type
non-abstract, and use that as the list type, and write the other
constraints in another way (e.g. using Schematron rules, a RELAX NG
grammar or just in natural language documentation as you would with a
DTD).

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

Received on Monday, 25 February 2002 04:34:28 UTC