3

I'm trying to build an element type that keep a list of change element type that is the base type of several other child type. I got this code :

<xs:complexType name="change_list" >
    <xs:annotation>
      <xs:documentation>List of changes.</xs:documentation>
    </xs:annotation>

    <xs:sequence>
      <xs:choice minOccurs="1" maxOccurs="unbounded" >

        <xs:element name="change" type="aos:change" >
          <xs:annotation>
            <xs:documentation>Generic or specific type of change.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="activate" type="aos:activate" >
          <xs:annotation>
            <xs:documentation>Change that will activate an element or do nothing if already activated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="deactivate" type="aos:deactivate" >
          <xs:annotation>
            <xs:documentation>Change that will deactivate an element or do nothing if already deactivated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="switch" type="aos:switch" >
          <xs:annotation>
            <xs:documentation>Change that will activate the element if deactivated or deactivate it if activated.</xs:documentation>
          </xs:annotation>
        </xs:element>

        <xs:element name="transform" type="aos:transform" >
          <xs:annotation>
            <xs:documentation>
              Change that will modify the geometric state of the element
              by applying one or several geometric transformations.
            </xs:documentation>
          </xs:annotation>
        </xs:element>


      </xs:choice>
    </xs:sequence>

Im' using CodeSynthesis to generate C++ code.

Now, that seems overkill because here we clearly define access to different types. I think what I want is something simpler like :

List of changes.

    <xs:sequence>
      <xs:choice minOccurs="1" maxOccurs="unbounded" >

        <xs:element name="change" type="aos:change" >
          <xs:annotation>
            <xs:documentation>Generic or specific type of change.</xs:documentation>
          </xs:annotation>
        </xs:element>

      </xs:choice>
    </xs:sequence>

Now that don't allow me to have different tags for different subtypes of changes. So I thought maybe a good solution might be to use substitution group.

But then I would loose the ability to use the specific sub-type's attributes and elements.

Is the original solution good to do that (having a list of base type object that can get child types too)?

Klaim
  • 67,274
  • 36
  • 133
  • 188
  • 1
    What is exactly the problem with substitution groups? It is a common practice to model polyformism in XML Schema. – lexicore Nov 25 '10 at 13:27
  • Maybe I'm wrong but AFAIK using substitution group is a kind of alias, right? Then I can use it as an alias for the "change" tag, am I correct? Then I cannot use change-tag-child-element-type-specific elements and attributes. Am I correct? – Klaim Nov 25 '10 at 14:51

3 Answers3

3

Dont know if you still need an answer... But the following schema does what you need.

First of all the base type and two concrete subtypes (make sure, that your base class has abstract="true" set):

<xs:complexType abstract="true" name="BaseTask">
  <xs:sequence>
    <xs:element name="Name" type="xs:string" />
  </xs:sequence>
</xs:complexType>

<xs:complexType name="ConcreteTask1">
  <xs:complexContent>
    <xs:extension base="BaseTask">

    </xs:extension>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="ConcreteTask2">
  <xs:complexContent>
    <xs:extension base="BaseTask">
      <xs:sequence>
        <xs:element name="Description" type="xs:string" />
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

Then adding a list that holds elements that are subtypes of BaseTask:

<xs:element name="TaskList">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Tasks" minOccurs="0" maxOccurs="unbounded" type="BaseTask" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

The xml then looks like this:

<TaskList>
  <Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask1">
    <Name>Foo1</Name>
  </Tasks>
  <Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask2">
    <Name>Foo2</Name>
    <Description>Test</Description>
  </Tasks>
</TaskList>
Thekwasti
  • 222
  • 2
  • 10
0

What you want is not possible in xml-schema. You can extend (or restrict) a defined type but then this is a new type. Subtyping polymorphism (inclusion polymorphism) doesn't exist in xml-schema.

  • Then, there is no way to say that a sequence for example can have elements of one type or this type's children types? Or is there an equivalent in xsd that could help me solve my problem? – Klaim Dec 06 '10 at 14:32
0

It sounds like what you want is a list of changes, but you also want the type of change recorded in the list (activate, switch, etc).

What I would do is make a simple element called ChangeType element that would have a "type" attribute whose data type would be another element, ChangeTypeType which would be an enum of your valid changed types. For example:

<element name="ChangeList" type="ChangeListType"/>    
<complexType name="ChangeListType">
    <annotation>
        <documentation>
            A list of changes
        </documentation>
    </annotation>
    <sequence>
        <element name="change" type="ChangeType" minOccurs="1" maxOccurs="unbounded">
            <annotation>
                <documentation>
                    A change event
                </documentation>
            </annotation>
        </element>
    </sequence>
</complexType>

<complexType name="ChangeType">
    <annotation>
        <documentation>
            A change unit
        </documentation>
    </annotation>
    <attribute ref="typeOfChange" use="required"/>
</complexType>

<attribute name="typeOfChange" type="ChangeTypeType">
    <annotation>
        <documentation>
            The kind of change
        </documentation>
    </annotation>
</attribute>

<simpleType name="ChangeTypeType">
    <annotation>
        <documentation>
            Describes the types of allowed changes
        </documentation>
    </annotation>
    <restriction base="token">
        <enumeration value="activate"/>
        <enumeration value="activate"/>
                    <enumeration value="switch"/>
                    <enumeration value="transform"/>
    </restriction>
</simpleType>

This would give you an XML document like:

<ChangeList>
    <change typeOfChange="activate/>
    <change typeOfChange="switch/>
    <change typeOfChange="transform/>
</ChangeList>
Gabriel Jiva
  • 159
  • 4
  • I already have that but that don't solve the problem : if you do that you can't access child element type specific content. For example if only switches have the "target" element( or even attributes), you cant set it in the list. – Klaim Dec 06 '10 at 23:28