RE: using xsd:choice + element value

The way you have modeled this requires a co-occurrence constraint, where the
value (as constrained in the enumeration) has bearing on the constraints of
another part. If modeled this way, you'd have to use something like
Schematron to express and enforce the constraint.

The trouble seems to be  that you're expressing meta-information in element
content. Whenever you see the modeling of "type" information in the element
content or attribute values, you'll likely have trouble expressing it fully
in Schema and trouble getting a schema-validating parser to enforce it.

If you want to have this enforced in Schema, you'd have to model it
differently, moving the differentiating information (dog or cat) into
elements (<dog> or <cat>), whereby the element occurrence determines the
desired type

<myPets>
	<dog>
			<name>Scooby</name>
		</dog>
		<cat>
			<name>Pyewacket</name>
		</cat>
	</myPets>


Here, we've moved the "type" information (for both "animal" and "name") into
the schema, where it arguably belongs. The idea is that the choice itself,
being meta-information, is represented as distinguishable types (not element
choice), and the "choosing" occurs by the validating parser identifying the
correct type. One way you can do this is to employ XML Schema substitution
groups. 

	<xs:element name="myPets">
		<xs:complexType>
			<xs:sequence>
				<xs:element ref="animal"/>
			</xs:sequence>
		</xs:complexType>
	</xs:element>


The (abstract) element animal (of abstract type animal) consists of a "name"
of type "animalName"

	<xs:element name="animal" type="animal" abstract="true"/>
	<xs:complexType name="animal">
		<xs:sequence>
			<xs:element name="name" type="animalName"/>
		</xs:sequence>
	</xs:complexType>

Then, "dog" and "cat" of types "dog" and "cat", respectively, are members of
this substitution group:

	<xs:element name="dog" type="dog" substitutionGroup="animal"/>
	<xs:element name="cat" type="cat" substitutionGroup="animal"/>



and can thus substitute for the element "animal" (since it's abstract, it
must be substituted for).

The respective types dog and cat restrict the type of the "name" element:

	<xs:complexType name="dog">
		<xs:complexContent>
			<xs:restriction base="animal">
				<xs:sequence>
					<xs:element name="name"
type="dogName"/>
				</xs:sequence>
			</xs:restriction>
		</xs:complexContent>
	</xs:complexType>
	<xs:complexType name="cat">
		<xs:complexContent>
			<xs:restriction base="animal">
				<xs:sequence>
					<xs:element name="name"
type="catName"/>
				</xs:sequence>
			</xs:restriction>
		</xs:complexContent>
	</xs:complexType>

so an "animal" has a "name"; specifically, a cat has a name (of type
catName) and a dog has a name (of type dogName).



With the names constrained as appropriate:

	<xs:simpleType name="animalName">
		<xs:restriction base="xs:string"/>
	</xs:simpleType>
	<xs:simpleType name="catName">
		<xs:restriction base="animalName">
			<xs:enumeration value="Pyewacket"/>
			<xs:enumeration value="Marmalade"/>
		</xs:restriction>
	</xs:simpleType>
	<xs:simpleType name="dogName">
		<xs:restriction base="animalName">
			<xs:enumeration value="Scooby"/>
			<xs:enumeration value="Rover"/>
		</xs:restriction>
	</xs:simpleType>


To make all of this validate correctly (complying with particle derivation
rules) , "animal"  is of abstract type "animal" and types "dog" and "cat"
are derived from "animal".   

When a validating parser encounters "dog", it validates that "dog" is one of
the legal substitutes for "animal", and then constrains dog to be of type
dog.  Same thing with "cat". If you want to add a new animal type, you
define another element in the "animal" substitution group, make it be of a
type that is subtype of the type "animal", and now another type of animal
will be recognized. 



Note that the element name for "dogName" and "catName"  is now just "name" -
type information has been driven into the type.

This is a pretty powerful representation pattern, and comes about as close
as possible to representing object class-instance relationships in Schema. 

The catName/dogName examples are weak rationale for using this mechanism,
especially since the types catName and dogName typically don't differ in any
meaningful way. Where the representation pattern really comes in useful is
where there are real type differences among the substitution elements, e.g.,
the sets of vaccines required for cats and dogs. It takes a why to get used
to expressing type information as XML Schema types and not as enumerated
element content or attribute values.


Mark

Mark Feblowitz                                   	
XML Architect
       [t]   617.715.7231                                     	
       [f]   617.495.0188
Frictionless Commerce Incorporated 	
       [e]  mfeblowitz@frictionless.com
       [w] http://www.frictionless.com
       [m] 400 Technology Square, 9th Floor
             Cambridge, MA 02139 
Open Applications Group Incorporated
       [e]  mfeblowitz@openapplications.org
       [w] http://www.openapplications.org 

 -----Original Message-----
From: 	Matt Long [mailto:mlong@phalanxsys.com] 
Sent:	Monday, May 27, 2002 7:36 AM
To:	'Eddie Robertsson'
Cc:	xmlschema-dev@w3.org
Subject:	RE: using xsd:choice + element value

Eddie,

Hmmmmm...

The primary issue is that a schema needs to implement a 'choice' based
on a prior element 'value'.   The animal schema below illustrates the
point that the qualifier value of "dog | cat" cannot qualify the choice
elements (dogName | catName).  In other words the schema is valid with

	<animalType>cat</animal>
	<dogName>Scooby</dogName>

which is not the intent and therefore is not properly communicated.  Is
this simply not possible???

<xsd:simpleType name="qualifier">
	<xsd:enumeration value="dog"/>
	<xsd:enumeration value="cat"/>
</xsd:simpleType>

<xsd:element name="animal" type="animalType"/>

<xsd:complexType name="animalType">
	<xsd:sequence>
		<xsd:element name="animalQualifier" type="qualifier"/>
		<xsd:choice>
			<xsd:element name="dogName" type="xsd:string"/>
			<xsd:element name="catName" type="xsd:string"/>
		</xsd:choice>
	</xsd:sequence>
</xsd:complexType>

> -----Original Message-----
> From: Eddie Robertsson [mailto:erobertsson@allette.com.au]
> Sent: Sunday, May 26, 2002 7:11 PM
> To: mlong@phalanxsys.com
> Cc: xmlschema-dev@w3.org
> Subject: Re: using xsd:choice + element value
> 
> Hi Matt,
> 
> No, you can't do that using the design you have in your schema.
However,
> if I understand your problem correct I think you can use the technique
> of using xsi:type in the instance document to specify which type an
> element should use from the instance document. Here is a modified
> version of your schema where complexTypes are used instead of groups:
> 
> <xsd:element name="whatIsIt" type="baseType"/>
> 
> <!-- Empty type that is used as a common base for personType and
> placeType -->
> <xsd:complexType name="baseType"/>
> 
> <!-- Type defining the person -->
> <xsd:complexType name="personType">
>     <xsd:complexContent>
>         <xsd:extension base="baseType">
>             <xsd:sequence>
>                 <xsd:element name="firstName" type="xsd:string"/>
>                 <xsd:element name="lastName" type="xsd:string"/>
>             </xsd:sequence>
>         </xsd:extension>
>     </xsd:complexContent>
> </xsd:complexType>
> 
> <!-- Type defining the place -->
> <xsd:complexType name="placeType">
>     <xsd:complexContent>
>         <xsd:extension base="baseType">
>             <xsd:sequence>
>                 <xsd:element name="country" type="xsd:string"/>
>                 <xsd:element name="city" type="xsd:string"/>
>             </xsd:sequence>
>         </xsd:extension>
>     </xsd:complexContent>
> </xsd:complexType>
> 
> Note that the whatIsIt element have the type baseType. Also, I have
> removed you qualifier element because instead of using an element to
> qualify which type is used we're going to use xsi:type in the instance
> to specify which of the derived types the whatIsIt element has. E.g.
> 
> <whatIsIt xsi:type="personType">
>     <firstName>aaa</firstName>
>     <lastName>bbb</lastName>
> </whatIsIt>
> 
> This will only validate the whatIsIt element if it has subelements
> matching the personType. The same applies for the placeType:
> 
> <whatIsIt xsi:type="placeType">
>     <country>aaa</country>
>     <city>bbb</city>
> </whatIsIt>
> 
> Is this something that would fit your requirement?
> 
> Cheers,
> /Eddie
> 
> 
> > Is it possible to utilize 'choice' from an element value (not purely
> > the existence of the element name)
> >
> > Example: a schema with a qualifier (1=person, 2=place)...so the
question
> > is how can one determine the group ref from the element value of
> > 'qualifier' element (or is it simply not possible)?
> >
> > -Matt Long
> >
> > Phalanx Systems, LLC
> >
> > <xsd:element name="whatIsIt" type="z:infoType"/>
> >
> > <xsd:complexType name="infoType">
> >
> > <xsd:sequence>
> >
> > <xsd:element name="qualifier" type="z:myQualType"/>
> >
> > <!-how can 'qualifier' qualify the choice of group reference à
> >
> > <xsd:choice>
> >
> > <xsd:group ref="z:personGroup"/>
> >
> > <xsd:group ref="z:placeGroup"/>
> >
> > </xsd:choice>
> >
> > </xsd:sequence>
> >
> > </xsd:complexType>
> >
> > <xsd:group name="personGroup">
> >
> > <xsd:sequence>
> >
> > <xsd:element name="firstName" type="xsd:string"/>
> >
> > <xsd:element name="lastName" type="xsd:string"/>
> >
> > </xsd:sequence>
> >
> > </xsd:group>
> >
> > <xsd:group name="placeGroup">
> >
> > <xsd:sequence>
> >
> > <xsd:element name="country" type="xsd:string"/>
> >
> > <xsd:element name="city" type="xsd:string"/>
> >
> > </xsd:sequence>
> >
> > </xsd:group>
> >
> > <xsd:simpleType name="myQualType">
> >
> > <xsd:restriction base="xsd:string">
> >
> > <xsd:enumeration value="1"/>
> >
> > <xsd:enumeration value="2"/>
> >
> > </xsd:restriction>
> >
> > </xsd:simpleType>
> >

Received on Tuesday, 28 May 2002 10:41:27 UTC