xsdeclipse-emf

<choice> not support when writing xsd schema for EMF


I am writing a schema for EMF to describe general graphs. The problem is that if this is directed graph, then the edge should have properties of src_node and dst_node, otherwise it has node_one and node_two. I tried to use "choice" to have mutally exclusive elements but in EMF it functions the same as "sequence". e.g a similar problem for NodeProperty

    <xsd:complexType name="NodeProperty">
            <xsd:choice>
                  <xsd:element name="StringValue" type="xsd:string"/>
                  <xsd:element name="IntValue" type="xsd:int"/>
                  <xsd:element name="DoubleValue"  type="xsd:double"/>
            </xsd:choice>
            <xsd:attribute name="Property" type="xsd:string"/>
    </xsd:complexType>

Another problem in substitutionGroup is that src_node and dst_node are claimed be to unresolved by EMF. The complete code:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:simpleType name="GraphType">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="Directed"/>
        <xsd:enumeration value="Undirected"/>
    </xsd:restriction>
</xsd:simpleType>

    <xsd:complexType name="NodeProperty">
            <xsd:choice>
                  <xsd:element name="StringValue" type="xsd:string"/>
                  <xsd:element name="IntValue" type="xsd:int"/>
                  <xsd:element name="DoubleValue"  type="xsd:double"/>
            </xsd:choice>
            <xsd:attribute name="Property" type="xsd:string"/>
    </xsd:complexType>

<xsd:complexType name="Node">
            <xsd:sequence>
          <xsd:element maxOccurs="unbounded" minOccurs="0"
                    name="Node" type="lib:NodeProperty"/>
            </xsd:sequence>
            <xsd:attribute name="NodeName" type="xsd:string" />
</xsd:complexType>

    <xsd:element name="src_node" type="xsd:anyURI" ecore:reference="lib:Node"/>
    <xsd:element name="node_one" type="xsd:anyURI" substitutionGroup="src_node"/>
    <xsd:element name="dst_node" type="xsd:anyURI" ecore:reference="lib:Node"/>
    <xsd:element name="node_two" type="xsd:anyURI" substitutionGroup="dst_node"/>

    <xsd:complexType name="Edge">
    <xsd:sequence>
            <xsd:element ref="src_node"/>
            <xsd:element ref="dst_node"/>
    </xsd:sequence>
    </xsd:complexType>

<xsd:complexType name="GeneralGraph">
    <xsd:sequence>
        <xsd:element name="name" type="xsd:string"/>
        <xsd:element name="type" type="lib:GraphType"/>
        <xsd:element name="NodeList">
                            <xsd:complexType>
                                    <xsd:sequence>
                              <xsd:element maxOccurs="unbounded" minOccurs="0"
                                    name="Node" type="lib:Node"/>
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>                                                                                                                                                                          
        <xsd:element name="EdgeList">
                            <xsd:complexType>
                                    <xsd:sequence>
                              <xsd:element maxOccurs="unbounded" minOccurs="0"
                                    name="Edge" type="lib:Edge"/>
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>                                                                                                                                                                          
    </xsd:sequence>
</xsd:complexType>


Solution

  • Yes. Substitution groups apply to global elements. So move your elements out of your type and reference to them in the type.

    <xsd:element name="src_node" type="xsd:anyURI" ecore:reference="lib:Node"/>
    <xsd:element name="node_one" type="xsd:anyURI" substitutionGroup="src_node"/>
    <xsd:element name="dst_node" type="xsd:anyURI" ecore:reference="lib:Node"/>
    <xsd:element name="node_two" type="xsd:anyURI" substitutionGroup="dst_node"/>
    
    
    <xsd:complexType name="Edge">
            <xsd:sequence>
                    <xsd:element ref="src_node"/>
                    <xsd:element ref="dst_node"/>
            </xsd:sequence>
    </xsd:complexType>
    

    Untested.

    The idea is that now node_one could be used instead src_node in Edge and node_two instead of node_two.

    Note that type of the substitutable must be derived from the type of the substitution group element. So I used anyURI just for example. You'll probably want to rework it.

    By the way I generally discourage usage of subsitition groups. Makes your XML unpredictable.