Can xsd parent element (base) be given default value in child (extension/restriction)? - xsd

I'm trying to do something like this:
<xs:complexType name="tSomeComponent">
<xs:sequence>
<xs:element name="table" type="xs:string" />
<xs:element name="key" type="tKey" />
<xs:element name="class" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="tStation">
<xs:complexContent>
<xs:restriction base="tSomeComponent">
<xs:sequence>
<xs:element name="table" type="xs:string" default="station" />
<xs:element name="name" type="xs:string" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
I know that table default value in child should be done by restriction but i want to extend and restrict at same time. I know that this can be solved by adding more types but that's an overkill.

Related

Using x:anyType instead of xsi:type gives Jaxb marshalling errors

I want to avoid xsi:type in an element and add the child elements at runtime based on some condition
I have option element defined as follows of type xs:anyType
<xs:complexType name="prod">
<xs:sequence>
<xs:element type="xs:anyType" name="option" minOccurs="0" maxOccurs="1"</xs:element>
</xs:sequence>
</xs:complexType>
used in element mapping as follows
<xs:element name="mappings">
<xs:complexType>
<xs:sequence>
<xs:element type="prod" name="productionSystem" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I have need to add following option type as one of the following
<xs:complexType name="Text">
<xs:sequence>
<xs:element type="xs:short" name="id" />
<xs:element type="xs:string" name="name" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Value">
<xs:sequence>
<xs:element type="xs:short" name="id" />
<xs:element type="xs:string" name="name" />
<xs:element name="psValue" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="value" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
so basically one element option can be either of type Text or Value.
I want to avoid xsi:type in the xml. hence defined as xs:anyType. However at runt time Jaxb Marshalling fails with error
"any of its super class is known to this context". How to ensure Text and Value are in Jaxb Context.
Can someone pls guide on same.
Thanks,
Anjana

xsd error in the following

here is the xml
<?xml version="1.0" encoding="utf-8"?>
<Modules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="XSDQu3.xsd">
<Module code="CSE1246">
<Name shortName="ADSA">Applied Data Structures and Algorithms</Name>
<Level>1</Level>
<ResourcePerson>
<Name>Anwar</Name>
<Surname>Chutoo</Surname>
</ResourcePerson>
</Module>
<Module code="CSE2041">
<Name shortName="Web 2">Web Technologies II</Name>
<Level>2</Level>
<ResourcePerson>
<FullName>Shehzad Jaunbuccus</FullName>
</ResourcePerson>
</Module>
</Modules>
i'm having an error at name. a resource person can either contain fullname or name and surname. please help. Am i correctly doing this part
here is the xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="NameNSurnameType">
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Surname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ResourcePersonType">
<xs:sequence>
<xs:choice>
<xs:element name="NameNSurnameType" type="NameNSurnameType"/>
<xs:element name="FullName" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:attribute name="code">
<xs:simpleType>
<xs:restriction base="xs:ID">
<xs:pattern value="CSE(\d{4})"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:complexType name="nameType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="shortName" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Modules">
<xs:complexType>
<xs:sequence>
<xs:element name="Module" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="nameType"/>
<xs:element name="Level" type="xs:positiveInteger"/>
<xs:element name="ResourcePerson" type="ResourcePersonType"/>
</xs:sequence>
<xs:attribute ref="code" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I can see your confusion; a choice "option" can be almost any particle; a compositor (such as xs:sequence or another xs:choice) would match the description. The minimum you need to do is change the following definition.
<xs:complexType name="ResourcePersonType">
<xs:sequence>
<xs:choice>
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Surname" type="xs:string"/>
</xs:sequence>
<xs:element name="FullName" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
If you want to reference the name as you seem to want to do it with the global complex type, then one can create a group and reference that instead. Below is a modified XSD consistent with the above scenario:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:group name="NameNSurnameType">
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Surname" type="xs:string"/>
</xs:sequence>
</xs:group>
<xs:complexType name="ResourcePersonType">
<xs:sequence>
<xs:choice>
<xs:group ref="NameNSurnameType"/>
<xs:element name="FullName" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:attribute name="code">
<xs:simpleType>
<xs:restriction base="xs:ID">
<xs:pattern value="CSE(\d{4})"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:complexType name="nameType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="shortName" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Modules">
<xs:complexType>
<xs:sequence>
<xs:element name="Module" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="nameType"/>
<xs:element name="Level" type="xs:positiveInteger"/>
<xs:element name="ResourcePerson" type="ResourcePersonType"/>
</xs:sequence>
<xs:attribute ref="code" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

XSD definition for simpleContent type string with attributes

I would like to define the XSD for:
<Group id="someid" parent="someid">some string</Group>
This is what I tried:
<xs:element name="Group" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:restriction base="xs:string">
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="parent" type="xs:IDREF" use="optional"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
</xs:element>
I use Visual Studio for the XSD design. The validator tells me (while underlining "<xs:restriction"):
"Undefined complexType 'http://w3.org/2001/XMLSchema:string' is used as base for a complex type restriction."
It's needed to use <xs:extension> instead of <xs:restriction>:
<xs:element name="Group" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="parent" type="xs:IDREF" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>

Problem with xml schema elements hierarchy

What's wrong with this xml schema? It doesn't parse correctly, and I can't realize a hierarchy between cluster(element)->host(element)->Load(element).
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cluster">
<xs:complexType>
<xs:sequence>
<xs:element ref="host"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="host">
<xs:complexType>
<xs:element ref="Load"/>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="Load">
<xs:complexType>
<xs:attribute name="usedPhisicalMemory" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:schema>
Thank you, Emilio
To allow something like this (I corrected the typo in "usedPhysicalMemory"):
<cluster>
<host name="foo">
<Load usedPhysicalMemory="500" />
</host>
<host name="bar">
<Load usedPhysicalMemory="500" />
</host>
</cluster>
This schema would do it:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cluster">
<xs:complexType>
<xs:sequence>
<xs:element ref="host" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="host">
<xs:complexType>
<xs:sequence>
<xs:element ref="Load" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="Load">
<xs:complexType>
<xs:attribute name="usedPhysicalMemory" type="xs:integer" />
</xs:complexType>
</xs:element>
</xs:schema>
From the MSDN on <xs:complexType> (because the spec makes my brain hurt):
If group, sequence, choice, or all is specified, the elements must
appear in the following order:
group | sequence | choice | all
attribute | attributeGroup
anyAttribute
Maybe someone else can point out the relevant section in the spec.
In the host element, the load element cannot be a child of complexType, you must have a sequence, etc. in between.

XML schema for elements with same name but different sub-structure depending on context

I try to define a schema for XML documents I receive.
The documents look like:
<root>
<items>
<group name="G-1">
<item name="I-1"/>
<item name="I-2"/>
<item name="I-3"/>
<item name="I-4"/>
</group>
</items>
<data>
<group name="G-1" place="here">
<customer name="C-1">
<item name="I-1" count="3"/>
<item name="I-2" count="4"/>
</customer>
<customer name="C-2">
<item name="I-3" count="7"/>
</customer>
</group>
</data>
</root>
I tried XmlSpy and xsd.exe from .NET 2.0. Both created schema definitions which allow below <group> any number of <item> and <customer> elements. But what I'm looking for should restrict <group> below <items> to <item> elements, and <group> below <data> to <customer> elements.
Is this something xml schema is not capable at all?
The key points (see XML Schema Runtime Polymorphism via xsi:type and Abstract Types for complete and correct context/placement/usage) are:
Create a base type with (abstract="true" to prevent it from being used directly)
Note: the ref attribute replaces the name attribute for elements defined elsewhere
<xs:complexType name="CustomerType" abstract="true" >
<xs:sequence>
<xs:element ref="cust:FirstName" />
<xs:element ref="cust:LastName" />
<xs:element ref="cust:PhoneNumber" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="customerID" type="xs:integer" />
</xs:complexType>
Create two or more derived types by extending or restricting the base type
<xs:complexType name="MandatoryPhoneCustomerType" >
<xs:complexContent>
<xs:restriction base="cust:CustomerType">
<xs:sequence>
<xs:element ref="cust:FirstName" />
<xs:element ref="cust:LastName" />
<xs:element ref="cust:PhoneNumber" minOccurs="1" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
and
<xs:complexType name="AddressableCustomerType" >
<xs:complexContent>
<xs:extension base="cust:CustomerType">
<xs:sequence>
<xs:element ref="cust:Address" />
<xs:element ref="cust:City" />
<xs:element ref="cust:State" />
<xs:element ref="cust:Zip" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Reference the base type in an element
<xs:element name="Customer" type="cust:CustomerType" />
In your instance XML document, specify the specific derived type as an xsi:type attribute
<cust:Customer customerID="12345" xsi:type="cust:MandatoryPhoneCustomerType" >
<cust:FirstName>Dare</cust:FirstName>
<cust:LastName>Obasanjo</cust:LastName>
<cust:PhoneNumber>425-555-1234</cust:PhoneNumber>
</cust:Customer>
or:
<cust:Customer customerID="67890" xsi:type="cust:AddressableCustomerType" >
<cust:FirstName>John</cust:FirstName>
<cust:LastName>Smith</cust:LastName>
<cust:Address>2001</cust:Address>
<cust:City>Redmond</cust:City>
<cust:State>WA</cust:State>
<cust:Zip>98052</cust:Zip>
</cust:Customer>
Yes, XSD can handle this. I generated this schema from Visual Studio 2008 (much faster than doing it by hand) and it will do what you're looking for:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="items">
<xs:complexType>
<xs:sequence>
<xs:element name="group">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="item">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="group">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="customer">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="item">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="count" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="place" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Resources