[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Extensible schemas and xs:any
Hi Murray, Questions about XML Schema are best directed to xmlschema-dev@w.... > 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/
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|