SledgeHammer
SledgeHammer

Reputation: 7736

How do I define this XSD?

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

Answers (2)

Kachna
Kachna

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

tom redfern
tom redfern

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

Related Questions