Reputation: 7736
Right now I have a working XSD for:
<Portal layout="blah" />
Now, I want to extend the system, so I can do (but I also want to support the OLD style above):
<Portal>
<layout xsi:type="type1">
<attribute ... />
<attribute ... />
<attribute ... />
</layout>
</Portal>
<Portal>
<layout xsi:type="type2">
<otherAttribute ... />
<someVal ... />
</layout>
</Portal>
So I want to have the legacy simple string and then a more complex type switched on the xsi type... You should not be able to mix the two.
Is that possible?
Upvotes: 2
Views: 58
Reputation: 2961
I try to simplify the problem like this: the element Portal
allow more complex combinations, such as either a layout
expressed as an attribute or expressed as element. so we have the following content models:
<Portal layout="blah" />
<Portal>
<layout >
<attribute ... />
<attribute ... />
</layout>
</Portal>
To do so, you will define a base type that is a superset of both content models:
<xs:complexType name="PortalBase" abstract="true">
<xs:sequence>
<xs:element ref="layout" minOccurs="0"/>
</xs:sequence>
<xs:attribute ref="layout"/>
</xs:complexType>
This base type accepts portal
elements with optional layout
defined as attribute or element. We can derive by restriction a first type which will accept only layout
attribute:
<xs:complexType name="layoutAttribute">
<xs:complexContent>
<xs:restriction base="PortalBase">
<xs:attribute ref="layout" use="required"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
We can derive a second type that accepts only layout
defined as element:
<xs:complexType name="layoutElement">
<xs:complexContent>
<xs:restriction base="PortalBase">
<xs:sequence>
<xs:element ref="layout" minOccurs="1"/>
</xs:sequence>
<xs:attribute ref="layout" use="prohibited"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
we can use them in the schema to define the portal
element as having a type PortalBase
:
<xs:element name="portal" type="PortalBase"/>
Then we can use them in the instance documents to declare which derived type we are using:
<portal xsi:type= "layoutElement">
<layout attr1=""/>
</portal>
or:
<portal xsi:type= "layoutAttribute" layout="blah"/>
Upvotes: 1
Reputation: 31780
You can achieve this by using the Mixed Content attribute in your definition for the Portal type.
Something like:
<xs:element name="Portal">
<xs:complexType mixed="true"> <!-- this allows "old school" text content -->
<xs:choice minOccurs="0"> <!-- this allows use of one of the two layout types, or none at all. -->
<xs:element name="Layout1" type="layout1" />
<xs:element name="Layout2" type="layout2" />
</xs:sequence>
</xs:complexType>
</xs:element>
The restriction here is you cannot define elements of different types with the same name within the same "grouping" element (in this case the choice element)
Upvotes: 0