Reputation: 31686
This is a generalized example of what I am up against.
I have created derived types in my schema and want to create an element which is an unbounded list (sequence) which has a restrictition where only two of the three derived types is allowed.
To say it from a top level view, "I have events where in one situation can only have two types of events".
Here is how I have defined my events and a subsequent holder of the sequence. (This all works and is valid).
The abstract item is a complex type named "Event Base" and has a common attribute called Name:
<xs:complexType name="EventBase">
<xs:annotation><xs:documentation>***Abstract Event***</xs:documentation></xs:annotation>
<xs:attribute name="Name"/>
</xs:complexType>
Then I have three events derived from the abstract as follows
<xs:complexType name="DerivedEvent1">
<xs:complexContent>
<xs:extension base="EventBase">
<xs:attribute name="Alpha" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DerivedEvent2">
<xs:complexContent>
<xs:extension base="EventBase">
<xs:attribute name="Beta"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DerivedEvent3">
<xs:complexContent>
<xs:extension base="EventBase">
<xs:attribute name="Gamma"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
To facilliate a complex object to hold the derived events, I create a concrete "generic" event derived from the abstract complex
<xs:element name="Event" type="EventBase">
<xs:annotation><xs:documentation>A generic event derived from abstract.</xs:documentation></xs:annotation>
</xs:element>
Then I want to be able to hold the events, so I create a new complex object to hold the "generic" event shown above, but will actually hold derived events by the eventual consumer.
<xs:complexType name="EventsCollectionType">
<xs:annotation><xs:documentation>Holds derived events</xs:documentation></xs:annotation>
<xs:sequence>
<xs:element ref="Event" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
Finally I create an element derived from the collection type which will hold actual events:
<xs:element name="Events"><xs:annotation><xs:documentation>Concrete holder of events.</xs:documentation></xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element ref="Event" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The resulting xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Events xsi:noNamespaceSchemaLocation="file:///C:/StackOverflow.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Event xsi:type="DerivedEvent1" Name="D1" Alpha="Content1"/>
<Event xsi:type="DerivedEvent3" Name="D1" Gamma="Content3"/>
</Events>
So the question is, how can I create a final Event*s* element which will hold only specific xsi:typed items?
So in the case where a restriction held that only the derived types of 1 and 3 would be valid (as above); but if it had a derived type 2 it would be invalid.
I have created a public GIST (Constraint or Restriction on xsi:type)
Upvotes: 4
Views: 455
Reputation: 461
I may be wrong, but I don't think this is possible.
Within the Events collection you essentially want to have different structures but all with the same element name "Event". This goes against a fundamental constraint of schemas: http://www.w3.org/TR/xmlschema-1/#cos-element-consistent. Using xsi:type gives the schema processor a hint that will allow it to disambiguate this choice of structures thus avoiding violating this rule. It's essentially a work-around.
Could you not call each different things so you have a collection of "event1"s and "event3"s or an outer collection containing a sequence of optional "events1"s and "event3"s? It would be much easier to schema enforce the structure in this way. Also then you wouldn't require to use xsi:type at all. I'm not sure if you are using xsi:type in your instances to try to work around this limitation or for another reason but it may be easier for anybody using the schema to not have to worry about derived types.
Alternatively, you could potentially use another technology (eg schematron) to help enforce this constraint.
Upvotes: 1