- From: Roger L. Costello <costello@mitre.org>
- Date: Fri, 29 Mar 2002 08:23:27 -0500
- To: Jeni Tennison <jeni@jenitennison.com>
- CC: xmlschema-dev@w3.org, Simon.Cox@csiro.au, costello@mitre.org
Thanks for keeping me honest Jeni. I am eager to learn how to use this
design pattern! I learn best when I can see a concrete example, so how
about considering this example:
1. I have an abstract Publication element.
2. I then create two elements, Book and Magazine, which are
substitutable for Publication.
3. I have an element Catalogue whose contents is Publication.
Here's are the declarations for the above:
<xsd:element name="Publication" abstract="true"
type="PublicationType"/>
<xsd:element name="Book" substitutionGroup="Publication"
type="BookType"/>
<xsd:element name="Magazine" substitutionGroup="Publication"
type="MagazineType"/>
<xsd:element name="Catalogue">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Publication" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
[I have omitted the complexType declarations for PublicationType,
BookType, and MagazineType. Assume the later two derive from the
former.]
As we know, given the above declarations an instance document author is
empowered to populate <Catalogue> with any element that is in the
substitution group with Publication, e.g.,
<Catalogue>
<Book> ... </Book>
<Magazine> ... </Magazine>
<Book> ... </Book>
</Catalogue>
Further, we know that this design pattern is very extensible - new
elements may be added to the substitution group.
Now let's examine the new design pattern. As I understand it, the first
step is to embed the abstract element within a complexType, e.g.,
<xsd:complexType name="PublicationContainer">
<xsd:sequence>
<xsd:element ref="Publication"/>
</xsd:sequence>
</xsd:complexType>
And then other complexTypes are created which restrict this type, by
replacing the abstract element with a substitution group element, e.g.,
<xsd:complexType name="BookContainer">
<xsd:complexContent>
<xsd:restriction base="PublicationContainer">
<xsd:sequence>
<xsd:element ref="Book/>
</xsd:sequence>
</xsd:restriction>
<xsd:complexContent>
</xsd:complexType>
As the next step I assume you would then declare Catalogue to be of type
PublicationContainer:
<xsd:element name="Catalogue" type="PublicationContainer"/>
Correct?
What benefit is attained by doing this? As I see it, in an instance
document the contents of <Catalogue> must be elements that are
substitutable for the abstract Publication element:
<Catalogue>
<Book> ... </Book>
<Magazine> ... </Magazine>
<Book> ... </Book>
</Catalogue>
This is exactly what we had above, but achieved at a cost of an
indirection. Obviously there is some benefit that I am not seeing. Can
you explain the benefit that is gained by embedding the elements (e.g.,
Publication, Book) within a complexType? Thanks! /Roger
Jeni Tennison wrote:
>
> Hi Roger,
>
> >> In our schemas we have a /lot/ of cases following a general
> >> pattern:
> >>
> >> 1. Declare an element to act as head of substitition group;
> >> 2. Declare non-abstract elements in the substitution group,
> >> with a type derived from the type of the head by restriction;
> >> 3. Define a complex type which contains the abstract head element;
> >> 4. Define a restriction of the container which specifies that
> >> a particular concrete member element is present.
> >>
> >> This appears to be pretty much how substitution groups were
> >> designed to be used.
> >
> > Simon, I respectfully disagree. That is NOT how substitution groups
> > were designed to be used. The intended purpose of substitution
> > groups is to enable substitutability in **instance documents**. You
> > are attempting to perform substitution in the **schema**, which in
> > the least is bad practice, if not outright incorrect (I need to
> > check the spec on this).
>
> It certainly isn't *incorrect*. When a validator checks whether a
> derivation by restriction is valid, it substitutes any particles that
> are head elements of substitution groups with a choice model group
> containing the head and members of the substitution group [1]. The
> restriction is legal as long as it would have been a legal restriction
> if that choice group had been defined originally.
>
> I don't know whether using substitution groups as Simon is was
> *intended* or not, but it certainly seems to be a growing pattern of
> use. As I see it, when you define the content model for a type, you
> can set constraints on the elements in the content at three levels:
>
> - constrain their namespace (using xs:any)
> - constrain their type (using substitution groups)
> - constrain their name (using normal element particles)
>
> All of these are potentially useful types of constraints. And as I see
> it, the constraints or lack of them can be useful both in the instance
> (as you describe) and in the type hierarchy within the schema (as
> Simon described).
>
> Putting it another way: when you define a common type, to act as an
> ancestor for a number of types, the commonality between the types
> might be of several kinds:
>
> - they might contain the same element(s)
> - they might have the same attribute(s)
> - they might be used by the same element(s)
> - they might contain element(s) that have the same type
>
> Using substitution groups as Simon is reflects the latter kind of
> commonality, where two types contain elements of the same type,
> usually used in the same way.
>
> Can you explain more about why you think that it's bad practice?
>
> Cheers,
>
> Jeni
>
> [1] http://www.w3.org/TR/xmlschema-1/#cos-particle-restrict
>
> ---
> Jeni Tennison
> http://www.jenitennison.com/
Received on Friday, 29 March 2002 08:24:44 UTC