XSD and polymorphism

I will repeat this question a little the first time it was asked incorrectly.

I have it:

<xsd:complexType name="A"> <xsd:sequence> <xsd:element name="options" type="options"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="B"> <xsd:complexContent> <xsd:element name="options" type="ex_options"/> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="options"> <xsd:sequence> ...some options </xsd:sequence> </xsd:element> <xsd:complexType name="ex_options"> <xsd:complexContent> <xsd:extension base="options"> <xsd:sequence> ...some more options </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:element> 

So basically I have class A with an inner class of options. Class B inherits from class A, and I want B.options to inherit from A.options, so when we do web services we only need to pass a, and when we call getOptions, it will return the correct B.options object. Currently, with the way xsd costs, I get a message that several elements with name parameters with different types appear in the model group. Errors are in type B.

+4
source share
3 answers

Just enter w / elements of type B, and then use then to decorate the elements of the instance document, as described below, with the corresponding xsi: type attribute value


<xsd:complexType name="B">

<xsd:complexContent>
<xsd:element name="options" type="ex_options"/>
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="options">
<xsd:sequence>
...some options
</xsd:sequence>
</xsd:element>

<xsd:complexType name="ex_options">
<xsd:complexContent>
<xsd:extension base="options">
<xsd:sequence>
...some more options
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:element>

and then "decorate" your instance element as

<options xsi:type="ex_options">... (this will work)

or

<options xsi:type="options">... (I think you can do this as long as the base xsi:type is not abstract)

If it turns out that you cannot decorate w / base xsi: type, then you can always “cheat” by creating an empty base type, and then expanding the careful design to achieve the two desired formats.

See this post for more details and links.

+4
source

You can make the options sequence open so that you can have any number of parameters, and then check existing parameters based on the attribute value. For example, in the following diagram, the options list has a type attribute of either A or B , indicating which options should actually be displayed:

 <?xml version="1.0" encoding="utf-8" ?> <xs:schema targetNamespace="http://tempuri.org/XMLSchema.xs" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xs" xmlns:mstns="http://tempuri.org/XMLSchema.xs" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- Elements for document structure. --> <!-- This section is just for validating my example file to --> <!-- demonstrate the schema. --> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element name="elementA" type="A" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="elementB" type="A" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <!-- The important part of the schema. --> <!-- Types --> <!-- A has options of type options. --> <xs:complexType name="A"> <xs:sequence> <xs:element name="options" type="options"/> </xs:sequence> </xs:complexType> <!-- Options specifies a options with a type attribute specifying which options will be available. --> <xs:complexType name="options"> <xs:sequence> <xs:element name="option" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="type" use="optional" default="A"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="A"/> <xs:enumeration value="B"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:schema> 

Here is an example XML for this schema.

 <?xml version="1.0" encoding="utf-8"?> <root xmlns="http://tempuri.org/XMLSchema.xs"> <elementA> <options type="A"> <option>Test-A</option> <option>Test2-A</option> </options> </elementA> <elementB> <options type="B"> <option>Test-B</option> <option>Test2-B</option> <option>Test3-B</option> <option>Test4-B</option> </options> </elementB> </root> 
0
source

You can also use a constraint, not an extension, but this is not the best solution, because the constraint removes all the basic definitions. The best case is to use xsi: type at runtime (in instances of XML elements), as described in another answer.
More than one example of using xsi: type is here: http://www.xfront.com/ElementHierarchy.html

 <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <!-- Root element --> <xsd:element name="root" type="B"/> <!-- Base abstract type --> <xsd:complexType name="A" abstract="true"> <xsd:sequence> <!-- Option that we will override --> <xsd:element name="options" type="options"/> </xsd:sequence> </xsd:complexType> <!-- Derived type --> <xsd:complexType name="B"> <xsd:complexContent> <!--Overriding --> <xsd:restriction base="A"> <xsd:sequence> <xsd:element name="options" type="ex_options"/> </xsd:sequence> </xsd:restriction> </xsd:complexContent> </xsd:complexType> <!-- Base included class --> <xsd:complexType name="options"> <xsd:sequence> <xsd:element name="baseOption"/> </xsd:sequence> </xsd:complexType> <!-- Overriding of included class --> <xsd:complexType name="ex_options"> <xsd:complexContent> <xsd:restriction base="options"> <xsd:sequence> <xsd:element name="overridedOption"/> </xsd:sequence> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:schema> 

In pseudo CiXML, it would be something like this:

 { B root; abstract class A { options options; } class B override A { ex_options options; } class options { empty baseOption; } class ex_option override options { empty overridedOption } } 

Here is an example XML:

 <?xml version="1.0" encoding="UTF-8"?> <root xsi:noNamespaceSchemaLocation="polymorphism.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <options> <overridedOption/> </options> </root> 
0
source

All Articles