XSD and polymorphism - xsd

I am kinda repeating this question bit the 1st time it was asked incorrectly.
I have this:
<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 that when we do webservices we only need to pass a and when we call getOptions it will return the right object B.options. Currently with the way the xsd stands I get an error saying multiple elements with name options with different types appear in the model group. The errors is in the B type.

Just stick with elements of type B and then use then decorate your instance document elements as described below with the appropriate 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 either
<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 can't decorate with the base xsi:type,
then you can always "cheat" by creating an empty base type and then
extending by careful construction to arrive at your two desired formats.
See this post for more elaboration & links.

You could make the options sequence open-ended so you can have any number of options and then validate the existing options based on an attribute value. For example, in the following schema, the options list has a type attribute of either A or B, indicating which options should actually get listed:
<?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 of the 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>

You may also use restriction rather than extension, but it is not best solution, because restriction removes all base definitions. Better case is use xsi:type at runtime (in XML instances of elements) like described in other answer.
More 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 will something like:
{
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 the 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>

Related

Is It Impossible to have elements with same name in xsd?

My XML looks like . I have two elements with same name. But I am not being able to get those elements in XSD.
Here Book is the element that appears twice but has different attributes. All attributes in their respective Book elements are required.
The error says
Element Books is not consistent with element Books
XML :
<TestRoot>
<Test Shelf="1">
<Value>
<Book Name="Wolves" />
</Value>
</Test>
<Test Shelf="2">
<Value>
<Book Name="Dogs" Pages="500" Photos="50" />
</Value>
</Test>
</TestRoot>
My XSD looks like :
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema....>
<xsd:element name="TestRoot">
<xsd:complexType>
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="Test" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:choice>
<xsd:element name="Value">
<xsd:complexType>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="Book">
<xsd:complexType>
<xsd:attribute name="Name" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="40"/>
<xsd:enumeration value="Wolves"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="Book">
<xsd:complexType>
<xsd:attribute name="Book" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="40"/>
<xsd:enumeration value="Dogs"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="Pages" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="50"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="Photos" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="24"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="Shelf" use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="100"/>
<xsd:enumeration value="1"/>
<xsd:enumeration value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Not sure where I am wrong ? Any help?
Try something like this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestRoot" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="TestRoot" msdata:IsDataSet="true" msdata:Locale="en-US">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Test">
<xs:complexType>
<xs:sequence>
<xs:element name="Value" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<!-- the <Book> node is just of "BookType" type -->
<xs:element name="Book" type="BookType" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Shelf" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
<!-- define the "BookType" which represents a single <Book> node -->
<xs:complexType name="BookType">
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="Pages" type="xs:string" />
<xs:attribute name="Photos" type="xs:string" />
</xs:complexType>
</xs:schema>
This XSD defines a new complex type BookType which is used to define how the <Book> nodes inside <Value> look like.
In general, I would also define a complex type for any of the XML nodes you have - I'd create a ValueType to handle how a <Value> node is made up, and I'd create a TestType for <Test> and a TestRootType for the <TestRoot> as well.
Having those really deeply nested XSD structures makes it really hard to "grasp" what's going on - defining a type for each node and then assigning them to the nodes makes it much more readable and understandable, in my opinion

xsd restriction in extended element

Suppose I have an element A and an element B extended from A as shown below.
<xsd:complexType name="A">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string"/>
</xsd:sequence>
<xsd:complexType>
<xsd:complexType name="B">
<xsd:complexContent>
<xsd:extension base="A">
<xsd:sequence>
<xs:element name="anotherVariable" type="xs:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
I have an usecase where desiredVariable in A can take any value and the same desiredVariable in B should be a fixed value. ie I have to apply restiction on desiredValue in B. How can I do that?
In general, XML 1.0 does not allow conditional data. But you can acheive what you want through extensions. This is how to implement it in XML 1.0:
You'll need to define the base element as abstract if you want to enforce the limitations. In the XML file they will need to specify the extension they are implementing. You need to define your restrictions separately.
XSD:
<xsd:complexType name="A" abstract="true">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string"/>
</xsd:sequence>
<xsd:complexType>
<xsd:complexType name="B">
<xsd:complexContent>
<xsd:extension base="A">
<xsd:restriction base="checksumType">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string" fixed="FixedValue"/>
<xs:element name="anotherVariable" type="xs:stringLimitedType"/>
</xsd:sequence>
</xsd:restriction>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:simpleType name="stringLimitedType">
<xsd:restriction base="xs:string">
<xsd:pattern value="([a-zA-Z0-9])*"/>
</xsd:restriction>
</xsd:simpleType>
XML:
<A namespace:type="B">
...
</A>
See the following for more on abstraction and extensions:
XSD schema abstract type problem
I have heard there are more options when using XML 1.1.

XSD extend restricted type

Can you have an allready restricted type and then derive from this type by extension and add elements that do not fit to a base type?
<xsd:complexType name="absHcontainerType">
<xsd:complexContent>
<xsd:restriction base="e:urContentType">
<xsd:sequence>
<xsd:element ref="e:absMcontainer" minOccurs="0"
maxOccurs="1" />
<xsd:element ref="e:absHtitle" minOccurs="1" maxOccurs="unbounded" />
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element ref="e:absMcontainer" />
<xsd:element ref="e:absHcontainer" />
<xsd:element ref="e:absContainer" />
</xsd:choice>
</xsd:sequence>
<xsd:attributeGroup ref="e:typehcontainer" />
<xsd:attributeGroup ref="e:anyattr" />
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
And then derive this like this:
<xsd:complexType name="absHcontainerType2">
<xsd:complexContent>
<xsd:extension base="absHcontainerType">
<xs:sequence>
<xs:element name="xy" type="xs:string"/>
<xs:element name="xyz" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xsd:complexContent>
</xsd:complexType>
As long as you don't put back things that got restricted away, I wouldn't expect a problem. Are you in fact getting an error when you try it?

Limit value of element to value in other element XSD

Given the following type:
<xsd:complexType name="Options">
<xsd:sequence>
<xsd:element name="option" maxOccurs="unbounded">
<xsd:complexType>
<xsd:all>
<xsd:element name="id" type="xsd:integer" />
<xsd:element name="label" type="xsd:string" />
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="dependency" type="xsd:integer" minOccurs="0" />
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
How can I express that a dependency of one option must exist as an id of a different option?
I think I'm supposed to be using xsd:key and xsd:keyref, but having trouble understanding how to use them.
XSD 1.0 doesn't support this. XSD 1.1 supports Conditional Types and assertions which might allow you to do this. For xsd 1.0 you can use Schematron to achieve this.
Constraints can only be expressed in the context of an element.
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Options">
<xsd:sequence>
<xsd:element name="option" maxOccurs="unbounded">
<xsd:complexType>
<xsd:all>
<xsd:element name="id" type="xsd:integer"/>
<xsd:element name="label" type="xsd:string"/>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
<xsd:element name="dependency" type="xsd:integer" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="Options" type="Options">
<xsd:key name="PK">
<xsd:selector xpath="option"/>
<xsd:field xpath="id"/>
</xsd:key>
<xsd:keyref name="FK" refer="PK">
<xsd:selector xpath="option"/>
<xsd:field xpath="dependency"/>
</xsd:keyref>
</xsd:element>
</xsd:schema>
If you wish to have this type referenced in multiple instances, along with the constraints you've indicated, then you will have to always define a global element, and then ref that element in your specific contexts.
I would mention that it is very important to understand of your use of the "different" word in your question. If you really mean it, then the above doesn't give you that.

XML Schema Choice - choose at lease one, but no repeat

How can I enforce to chose at lease one, but no repeat?
The following syntax allows any c element to repeat up to 3 times.
<choice minOccurs="1" maxOccurs="3">
<element name="c1" type="string" />
<element name="c2" type="string" />
<element name="c3" type="string" />
</choice>
thnx
steve
Loose the maxOccurs="3" and what you got is "choose at least one", no repeat.
For particles, the default is minOccurs="1"; a mandatory choice, where each option particle is itself mandatory, is your answer.
UPDATE: Based on your comment, if what you're looking is for any ordered combination of the particles you've described, this is the best you can get with XSD spec.
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="c1"/>
<xsd:element ref="c2" minOccurs="0"/>
<xsd:element ref="c3" minOccurs="0"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="c2"/>
<xsd:element ref="c3" minOccurs="0"/>
</xsd:sequence>
<xsd:element ref="c3"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
<xsd:element name="c1" type="xsd:string"/>
<xsd:element name="c2" type="xsd:string"/>
<xsd:element name="c3" type="xsd:string"/>
</xsd:schema>
This is messy already; if you're looking for a greater number of particles or any unordered combination, then I would change the model to something like this (these are XSD 1.0 limitations in action - it all has to do with limitations in the XPath syntax you can use for selectors/fields).
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="c" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="pk">
<xsd:selector xpath="*"/>
<xsd:field xpath="#code"/>
</xsd:key>
</xsd:element>
<xsd:element name="c" type="TC" abstract="true"/>
<xsd:element name="c1" type="TC1" substitutionGroup="c"/>
<xsd:element name="c2" type="TC2" substitutionGroup="c"/>
<xsd:element name="c3" type="TC3" substitutionGroup="c"/>
<xsd:complexType name="TC">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="code" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC1">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c1"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC2">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c2"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="TC3">
<xsd:simpleContent>
<xsd:restriction base="TC">
<xsd:attribute name="code" type="xsd:string" fixed="c3"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
</xsd:schema>
A sample XML would like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<c1 code="c1">c11</c1>
<c2 code="c2">c21</c2>
<c3 code="c3">c21</c3>
</root>
or this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<c2 code="c2">c21</c2>
<c1 code="c1">c11</c1>
</root>
Basically you're keying in on some component that makes your element unique, that is part of the data as opposed to a tag name. Again, messy, but as an exercise, it may give you an idea.

Resources