[
Lists Home |
Date Index |
Thread Index
]
Hi Murray,
Questions about XML Schema are best directed to xmlschema-dev@w3.org.
> What I want is a main schema that has an element that is allowed to
> have a sequence of any child nodes. To do this I defined a global
> type that has an xs:any content model (is that the right way to say
> this?).
More or less -- more technically you have a global complex type whose
content type is element-only with a content model which is a sequence
that has a single particle whose term is a wildcard. But your
description is easier to read!
> The document element then has a child element of this type. (see
> Main.xsd below)
>
> Then I would like to have a 'sub' schema that xs:imports the main
> schema - and in this sub schema I over-ride the "Stuff" element from
> the main schema and specify that the Stuff element must have certain
> elements. (see Sub.xsd below)
There's a problem here in that you can't override things from one
schema to another unless you use xs:redefine, which means that both
schemas have to share the same namespace.
> Finally - if I construct an instance document that specifies the
> location of both schemas - and includes the Stuff element with child
> elements as declared in the Sub schema - I try to validate this
> hybrid document against both schemas. (see Stuff.xml below)
There's a problem here because in your instance document, the actual
Stuff element that you use is main:Stuff rather than sub:Stuff. In
fact you have to do it like because main:Things has to contain
main:Stuff (which is actually declared locally), but of course that
means that the content model of main:Stuff is main:StuffType rather
than sub:MyStuffType.
Basically, you're not going to achieve your goal in this way. I can
think of two other approaches that you might try, though:
First, you could create an "adapter schema", with the 'main' target
namespace, that imports your sub schema and redefines the
main:StuffType type so that it references the elements in your sub
schema. Your sub schema needs to declare the elements that you want to
use within main:Stuff at a global level, so that they can be referred
to from the adapter schema:
<xs:schema targetNamespace="http://redcone.gbst.com/Sub"
xmlns:sub="http://redcone.gbst.com/Sub"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:element name="MyStuffA" type="xs:string"/>
<xs:element name="MyStuffB" type="xs:string"/>
</xs:schema>
The adapter schema needs to import this schema and redefine the main
schema, as follows:
<xs:schema targetNamespace="http://redcone.gbst.com/Main"
xmlns:main="http://redcone.gbst.com/Main"
xmlns:sub="http://redcone.gbst.com/Sub"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:import namespace="http://redcone.gbst.com/Sub"
schemaLocation="Sub.xsd" />
<xs:redefine schemaLocation="Main.xsd">
<xs:complexType name="StuffType">
<xs:complexContent>
<xs:restriction base="main:StuffType">
<xs:sequence>
<xs:element ref="sub:MyStuffA" />
<xs:element ref="sub:MyStuffB" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
</xs:schema>
Then in your instance document, you should only refer to this schema.
The second approach is to use a substitution group. Since you want
sub:MyStuffA and sub:MyStuffB to appear in sequence, and only once,
you have to do this at the main:Stuff/sub:Stuff level. To use a
substitution group, declare main:Stuff at a global level within the
main schema:
<xs:schema targetNamespace="http://redcone.gbst.com/Main"
xmlns:main="http://redcone.gbst.com/Main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:element name="Stuff" type="main:StuffType" />
<xs:complexType name="StuffType">
<xs:sequence>
<xs:any maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Things">
<xs:complexType>
<xs:sequence>
<xs:element name="Thing" type="xs:string"/>
<xs:element ref="main:Stuff"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then in your Sub schema, declare sub:Stuff to be part of the
substitution group of main:Stuff, as follows:
<xs:schema targetNamespace="http://redcone.gbst.com/Sub"
xmlns:main="http://redcone.gbst.com/Main"
xmlns:sub="http://redcone.gbst.com/Sub"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:import namespace="http://redcone.gbst.com/Main"
schemaLocation="Main.xsd"/>
<xs:element name="Stuff" type="sub:MyStuffType"
substitutionGroup="main:Stuff" />
<xs:complexType name="MyStuffType">
<xs:complexContent>
<xs:restriction base="main:StuffType">
<xs:sequence>
<xs:element name="MyStuffA" type="xs:string"/>
<xs:element name="MyStuffB" type="xs:string"/>
</xs:sequence>
</xs:restriction >
</xs:complexContent>
</xs:complexType>
</xs:schema>
Since sub:Stuff is part of the substitution group of main:Stuff, you
can replace main:Stuff with sub:Stuff wherever it appears within your
instance document. So your instance document should look like:
<main:Things xmlns:main="http://redcone.gbst.com/Main"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sub="http://redcone.gbst.com/Sub"
xsi:schemaLocation="http://redcone.gbst.com/Sub
Sub.xsd">
<main:Thing>String</main:Thing>
<sub:Stuff>
<sub:MyStuffA>blah</sub:MyStuffA>
<sub:MyStuffB>blad</sub:MyStuffB>
</sub:Stuff>
</main:Things>
Again, I'd only reference the one schema -- that for Sub.xsd -- though
it wouldn't do any harm if you referenced Main.xsd if you wanted to.
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
|