I've created a key/keyref on the root element in order to create document-wide uniqueness based on the specified element.
Therefore, via .//foo/#name every occurrence of #name across all instances of foo must be unique; likewise for .//bar/#name. This seems to be working fine. These are referenced by .//foo-ref/#name-ref and .//bar-ref/#name-ref respectively, also defined at the root node.
However, I've gathered that one cannot create an optional key, and this is presenting a bit of a problem. Semantically, by the nature of the conforming documents, a key is not required on every single instance of foo or bar. The instances of foo-ref/#name-ref would obviously need to target an existing foo/#name, but it isn't semantically invalid for a foo to be without a #name.
Is there any work-around for this? I don't like the idea of consumers having to define a key for every single element, when reasonably only a handful will need them.
Here's the example schema (of course, I'm not deploying some foobar schema, but the structure is identical; this is just a testing schema I've been toying with)
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="ref">
<xs:attribute name="name-ref" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="obj">
<xs:attribute name="name" type="xs:string" use="optional" />
</xs:complexType>
<xs:complexType name="foo">
<xs:complexContent>
<xs:extension base="obj">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="foo" type="foo" />
<xs:element name="bar" type="bar" />
<xs:element name="foo-ref" type="foo-ref" />
<xs:element name="bar-ref" type="bar-ref" />
</xs:choice>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="foo-ref">
<xs:complexContent>
<xs:extension base="ref" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="bar">
<xs:complexContent>
<xs:extension base="obj">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="bar" type="bar" />
<xs:element name="qux" type="qux" />
<xs:element name="bar-ref" type="bar-ref" />
</xs:choice>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="bar-ref">
<xs:complexContent>
<xs:extension base="ref" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="qux">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="foo" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:key name="foo">
<xs:selector xpath=".//foo" />
<xs:field xpath="#name" />
</xs:key>
<xs:key name="bar">
<xs:selector xpath=".//bar" />
<xs:field xpath="#name" />
</xs:key>
<xs:keyref name="foo-ref" refer="foo">
<xs:selector xpath=".//foo-ref" />
<xs:field xpath="#name-ref" />
</xs:keyref>
<xs:keyref name="bar-ref" refer="bar">
<xs:selector xpath=".//bar-ref" />
<xs:field xpath="#name-ref" />
</xs:keyref>
</xs:element>
</xs:schema>
Addendum
Just following up with my revisions thanks to #PetruGardea. So unique can be referenced by a keyref, who knew? (not me apparently)
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="foo" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:keyref name="foo-ref" refer="foo">
<xs:selector xpath=".//foo-ref" />
<xs:field xpath="#name-ref" />
</xs:keyref>
<xs:keyref name="bar-ref" refer="bar">
<xs:selector xpath=".//bar-ref" />
<xs:field xpath="#name-ref" />
</xs:keyref>
<!--
the use of xs:unique here, in lieu of xs:key allows for
nullable "keys", retaining referential integrity with the
above defined keyrefs. awesome possum.
-->
<xs:unique name="foo">
<xs:selector xpath=".//foo" />
<xs:field xpath="#name" />
</xs:unique>
<xs:unique name="bar">
<xs:selector xpath=".//bar" />
<xs:field xpath="#name" />
</xs:unique>
</xs:element>
Use xsd:unique; unlike a key, its matched value is either unique or nil (nil or not present).
Example:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="uk" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="fk" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:unique name="uq">
<xsd:selector xpath="uk"/>
<xsd:field xpath="#name"/>
</xsd:unique>
<xsd:keyref name="fk" refer="uq">
<xsd:selector xpath="fk"/>
<xsd:field xpath="#name"/>
</xsd:keyref>
</xsd:element>
</xsd:schema>
Sample (valid) XML:
<?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">
<uk name="name1"/>
<uk />
<fk/>
<fk name="name1"/>
</root>
Related
I have this xml-Schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Fussballmannschaft">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Stadt" type="xs:string" />
<xs:attribute name="Tabellenplatz" type="xs:string" />
<xs:element name="Spieler">
<xs:complexType>
<xs:attribute name="SpielerID" type="xs:string" />
<xs:keyref name="I_D" refer="Name" />
<xs:attribute name="Name" type="xs:string" />
<xs:element name="Torwart">
<xs:attribute name="GehealteneElfmeter" type="xs:integer" />
<xs:keyref name="ID_Torwart" refer="SpielerID" />
</xs:element>
<xs:element name="Verteidiger">
<xs:attribute name="GewonneneZweikaempfe" type="xs:integer" />
<xs:keyref name="ID_Verteidiger" refer="SpielerID" />
</xs:element>
<xs:element name="Stuermer">
<xs:attribute name="GeschosseneTore" type="xs:integer" />
<xs:keyref name="ID_Stuermer" refer="SpielerID" />
</xs:element>
</xs:complexType>
</xs:element>
</xs:complexType>
</xs:element>
</xs:schema>
and this sample:
<Fussballmannschaft Name="BVB">
<Stadt>Dortmund</Stadt>
<Tabellenplatz>3</Tabellenplatz>
<Spieler SpielerID="1">
<I_D>BVB</I_D>
<Name>Oliver</Name>
<Torwart>
<GehealteneElfmeter>20</GehealteneElfmeter>
<ID_Torwart>1</ID_Torwart>
</Torwart>
</Spieler>
<Spieler SpielerID="2">
<I_D>BVB</I_D>
<Name>Peter</Name>
<Torwart>
<GewonneneZweikaempfe>20</GewonneneZweikaempfe>
<ID_Verteidiger>2</ID_Verteidiger>
</Torwart>
</Spieler>
<Spieler SpielerID="3">
<I_D>BVB</I_D>
<Name>Paul</Name>
<Torwart>
<GeschosseneTore>20</GeschosseneTore>
<ID_Stuermer>3</ID_Stuermer>
</Torwart>
</Spieler>
</Fussballmannschaft>
But the parser says:
S4s-elt-character: Non-whitespace Characters Are Not Allowed In Schema Elements Other Than 'xs:appinfo' And 'xs:documentation'. Saw 'Dortmund'.
Do you know where the problem is?
The real reason you're getting this error,
S4s-elt-character: Non-whitespace Characters Are Not Allowed In Schema Elements Other Than 'xs:appinfo' And 'xs:documentation
is that you're attempting to validate your XML file as an XSD file.
So, fix the way you're invoking your validating parser so that you're validating your XML file against your XSD. See How to link XML to XSD using schemaLocation or noNamespaceSchemaLocation?
Additionally, there are a slew of other problems with your XSD itself. See collapsar's answer for help there.
We also had this problem. The reason was the address of the schema http:://xyz.xsd was replaced with https:://xyz.xsd. Our schema library was not able to forward to the https address via http one. So we simply changed the http adresses to https ones in the xml file.
Stadt and Tabellenplatz mustn't be xml elements but need to be attributes of the element Fussballmannschaft. This pattern repeats with the inner elements.
The schema also lacks structures to express repetition of elements (namely the Spieler element) and choices between player roles (Torwart,Verteidiger,Stuermer).
The use of the xs:keyref in the schema definition appears to be incomplete - the referenced keys are not specified as xs:key elements. In order to demonstrate this use, a new root element Fussball is defined, which should reflect the intent of the schema to formalize the notion of soccer teams. This new root element harbors the key and keyref definitions for the club name attribute and will be needed anyway as soon as multiple teams are to be represented in in a file (there must be a single root element in an xml file ).
The following pair of schema and sample passes the validation.
Schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Fussball">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="Fussballmannschaft">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="Spieler" maxOccurs="unbounded">
<xs:complexType mixed="true">
<xs:choice>
<xs:element name="Torwart">
<xs:complexType>
<xs:attribute name="GehalteneElfmeter" type="xs:integer" />
<xs:attribute name="ID_Torwart" type="xs:integer" />
</xs:complexType>
</xs:element>
<xs:element name="Verteidiger">
<xs:complexType>
<xs:attribute name="GewonneneZweikaempfe" type="xs:integer" />
<xs:attribute name="ID_Verteidiger" type="xs:integer" />
</xs:complexType>
</xs:element>
<xs:element name="Stuermer">
<xs:complexType>
<xs:attribute name="GeschosseneTore" type="xs:integer" />
<xs:attribute name="ID_Stuermer" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name="I_D" type="xs:string" />
<xs:attribute name="SpielerID" type="xs:integer" />
<xs:attribute name="Spielername" type="xs:string" />
</xs:complexType>
</xs:element><!-- Spieler -->
</xs:sequence>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Stadt" type="xs:string" />
<xs:attribute name="Tabellenplatz" type="xs:string" />
</xs:complexType>
<xs:key name="k-Spieler">
<xs:selector xpath="./Spieler"/>
<xs:field xpath="#SpielerID"/>
</xs:key>
<xs:keyref name="kref-Spieler" refer="k-Spieler">
<xs:selector xpath="./Spieler/Stuermer|./Spieler/Torwart|./Spieler/Verteidiger"/>
<xs:field xpath="#ID_Stuermer|#ID_Torwart|#ID_Verteidiger"/>
</xs:keyref>
</xs:element><!-- Fussballmannschaft -->
</xs:sequence>
</xs:complexType>
<!--
A 'key' tells you how to uniquely reference an element instance - eg. one among several soccer teams.
-->
<xs:key name="k-Verein">
<xs:selector xpath="./Fussballmannschaft"/>
<xs:field xpath="#Name"/>
</xs:key>
<!--
A 'keyref' specifies that some attribute value(s) are not only constrained by their datatype but must also uniquely identify a certain element in the file - a semantic relationship is established.
-->
<xs:keyref name="kref-Verein" refer="k-Verein">
<xs:selector xpath="./Fussballmannschaft/Spieler"/>
<xs:field xpath="#I_D"/>
</xs:keyref>
</xs:element><!-- Fussball -->
</xs:schema>
XML:
<Fussball>
<Fussballmannschaft Name="BVB" Stadt="Dortmund" Tabellenplatz="3">
<Spieler SpielerID="1" I_D="BVB" Spielername="Oliver">
<Torwart GehalteneElfmeter="20" ID_Torwart="1"/>
</Spieler>
<Spieler SpielerID="2" I_D="BVB" Spielername="Peter">
<Verteidiger GewonneneZweikaempfe="20" ID_Verteidiger="2"/>
</Spieler>
<Spieler SpielerID="3" I_D="BVB" Spielername="Paul">
<Stuermer GeschosseneTore="20" ID_Stuermer="3"/>
</Spieler>
</Fussballmannschaft>
</Fussball>
References
W3C XML Schema Definition
W3C XML Schema Definition / identity constraints
SO answer on the use of key and keyref
I am trying to create reusable element declarations for a web service to insert and update. I have the following declarations:
<xs:complexType name="commonEntity">
<xs:sequence>
<xs:element name="id" type="snt-common:id" minOccurs="0"
maxOccurs="1" />
<xs:element name="createdByID" type="snt-common:id"
minOccurs="0" maxOccurs="1" />
<xs:element name="createDate" type="snt-common:dateTime"
minOccurs="0" maxOccurs="1" />
<xs:element name="modifiedByID" type="snt-common:id"
minOccurs="0" maxOccurs="1" />
<xs:element name="modifyDate" type="snt-common:dateTime"
minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="contact">
<xs:complexContent>
<xs:extension base="snt-common:commonEntity">
<xs:sequence>
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element id="update" name="ContactUpdateRequest">
<xs:complexType>
<xs:complexContent>
<xs:restriction base="snt:contact">
<xs:sequence>
<xs:element name="id" type="snt-common:id" minOccurs="1"
maxOccurs="1" />
<xs:element name="modifyDate" type="snt-common:dateTime"
minOccurs="1" maxOccurs="1" />
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element id="insert" name="ContactInsertRequest">
<xs:complexType>
<xs:complexContent>
<xs:restriction base="snt:contact">
<xs:sequence>
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:element>
What I am trying to achieve is to create an insert and an update request, both of which are restrictions of contact. Contact in turn is an extension of commonEntity, which is used for all schemas as a base.
Insert works fine since there are no additional restrictions, but for update we require the id and modifyDate (this is how we enforce versioning) in the request. However, I get the following error when validating the schema:
Error for type '#AnonType_ContactUpdateRequest'. The particle of the type is not a valid restriction of the particle of
the base.
It seems as though I cannot restrict elements in the base element, commonEntity. I have tried reordering without success. Is this a nuance of XSD or am I missing something?
Update:
common.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://predictivesolutions.com/schema/common"
xmlns:snt-common="http://predictivesolutions.com/schema/common"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc" elementFormDefault="qualified"
jaxb:version="2.0">
<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings>
<xjc:javaType name="java.util.Calendar" xmlType="xs:dateTime"
adapter="com.ps.snt.ws.util.CalendarDateTimeAdapter" />
<xjc:javaType name="java.util.Calendar" xmlType="xs:date"
adapter="com.ps.snt.ws.util.CalendarDateAdapter" />
</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>
<!-- Creating this id type to use in the event we need to change to a long,
we can just do it here. -->
<xs:simpleType name="id">
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"></xs:minInclusive>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="dateTime">
<xs:restriction base="xs:dateTime">
<!-- 2013-11-06T11:17:17.043-05:00 -->
<xs:pattern value="\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\d[+\-]\d\d:\d\d" />
<!-- 2013-11-06T11:17:17-05:00 -->
<xs:pattern value="\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[+\-]\d\d:\d\d" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="string255">
<xs:restriction base="xs:string">
<xs:maxLength value="255" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="commonEntity">
<xs:sequence>
<xs:element name="id" type="snt-common:id" minOccurs="0"
maxOccurs="1" />
<xs:element name="createdByID" type="snt-common:id"
minOccurs="0" maxOccurs="1" />
<xs:element name="createDate" type="snt-common:dateTime"
minOccurs="0" maxOccurs="1" />
<xs:element name="modifiedByID" type="snt-common:id"
minOccurs="0" maxOccurs="1" />
<xs:element name="modifyDate" type="snt-common:dateTime"
minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:schema>
contact.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://predictivesolutions.com/schema/v1_1" xmlns:snt="http://predictivesolutions.com/schema/v1_1"
xmlns:snt-common="http://predictivesolutions.com/schema/common"
elementFormDefault="qualified">
<xs:import namespace="http://predictivesolutions.com/schema/common"
schemaLocation="../common.xsd" />
<xs:complexType name="contact">
<xs:complexContent>
<xs:extension base="snt-common:commonEntity">
<xs:sequence>
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- For transporting data -->
<xs:element id="contact" name="contact" type="snt:contact">
</xs:element>
</xs:schema>
ContactService.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://predictivesolutions.com/schema/v1_1" xmlns:snt="http://predictivesolutions.com/schema/v1_1"
xmlns:snt-common="http://predictivesolutions.com/schema/common"
elementFormDefault="qualified">
<xs:import namespace="http://predictivesolutions.com/schema/common"
schemaLocation="../common.xsd" />
<xs:include schemaLocation="contact.xsd" />
<!-- Request/Response for inserting data -->
<xs:element id="insert" name="ContactInsertRequest">
<xs:complexType>
<xs:complexContent>
<xs:restriction base="snt:contact">
<xs:sequence>
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:element>
<!-- Request/Response for updating data -->
<xs:element id="update" name="ContactUpdateRequest">
<xs:complexType>
<xs:complexContent>
<xs:restriction base="snt:contact">
<xs:sequence>
<xs:element name="id" type="snt-common:id" minOccurs="1"
maxOccurs="1" />
<xs:element name="modifyDate" type="snt-common:dateTime"
minOccurs="1" maxOccurs="1" />
<xs:element name="firstName" type="snt-common:string255"
minOccurs="0" maxOccurs="1" />
<xs:element name="lastName" type="snt-common:string255"
minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
I have just made my first attempt at XSD.
When I try and validate my XML against my XSD, I get the error:
Cannot find the declaration of element 'linkage'.
Below I give my XSD and a cut down version of my XML. I've tried adding a namespace qualifier to the top element in my XML and also to every element (changing the XSD to qualified) and it did not help. I'm obviously making a basic mistake. As I'm new to XSD, if you could include what I need to change in my XML and/or XSD I would be very grateful.
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.stephenwaring.me.uk/android/nestedsettings"
xmlns="http://www.stephenwaring.me.uk/android/nestedsettings"
elementFormDefault="unqualified">
<xs:element name="linkage">
<xs:complexType>
<xs:sequence>
<xs:element name="preference-screen" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="parent" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="child" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="key" type="xs:token" use="required" />
<xs:attribute name="reformat" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attributeGroup ref="keyed" />
<xs:attribute name="preference-screen" type="xs:token" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attributeGroup ref="keyed"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attributeGroup ref="defaults"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="defaults">
<xs:attribute name="html" type="xs:boolean" />
<xs:attribute name="prefix" type="xs:string" />
<xs:attribute name="suffix" type="xs:string" />
<xs:attribute name="separator" type="xs:string"/>
<xs:attribute name="reformat" type="xs:boolean" />
<xs:attribute name="shaddow" type="xs:boolean" />
<xs:attribute name="child-summary" type="xs:boolean" />
<xs:attribute name="shadow-separator" type="xs:string"/>
</xs:attributeGroup>
<xs:attributeGroup name="keyed">
<xs:attributeGroup ref="defaults" />
<xs:attribute name="key" type="xs:token" use="required" />
</xs:attributeGroup>
</xs:schema>
Cut down XML:
<?xml version="1.0" encoding="UTF-8"?>
<linkage
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://stevewaring.me.uk/android/nestedsettings nestedsettings.xsd"
xmlns="http://www.stevewaring.me.uk">
<preference-screen
key="preferences1">
<parent
key="prefFruit"
preference-screen="preferences2">
<child key="prefFruit1"/>
<child key="prefFruit2"/>
</parent>
</preference-screen>
</linkage>
Your XSD defines elements in http://www.stephenwaring.me.uk/android/nestedsettings whereas your document element is in http://www.stevewaring.me.uk. Make them to agree, one way or the other, and it should take care of the error you're having.
I've added a fixed XML, there's another issue related to use of unqualified elements.
<?xml version="1.0" encoding="UTF-8"?>
<linkage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.stephenwaring.me.uk/android/nestedsettings nestedsettings.xsd" xmlns="http://www.stephenwaring.me.uk/android/nestedsettings">
<preference-screen xmlns="" key="preferences1">
<parent key="prefFruit" preference-screen="preferences2">
<child key="prefFruit1"/>
<child key="prefFruit2"/>
</parent>
</preference-screen>
</linkage>
i want to create a XSD.
One optional element in the XSD is <PrintoutSettings OrderSource="NameOfOrder_X" .../>
Another substructure of the XSD is
<Order Name="NameOfOrder">...</Order>
<Order Name="NameOfOrder2">...</Order>
...
My aim is it, that the attribute NameOfOrder_X of <PrintoutSettings .../> must be a string that was defined in one of the <Order>...</Order> - elements.
How can i realize it in a XSD?
Kind regards
sb
---
---
Here some of my XSD:
<xs:complexType name="Order">
<xs:sequence>
<xs:element form="qualified" minOccurs="0" name="Documents" type="Documents"/>
</xs:sequence>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="Translator" type="xs:string" use="required"/>
<xs:attribute name="Proofreader" type="xs:string" use="required"/>
<xs:attribute name="LockedBy" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="Orders">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Order" type="Order"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="QQDBData">
<xs:sequence>
<xs:element minOccurs="0" name="Orders" type="Orders"/>
<xs:element minOccurs="0" name="LocalSettings" type="Settings"/>
</xs:sequence>
<xs:attribute default="2000-01-01" name="CreationDate" type="xs:date" use="optional"/>
</xs:complexType>
<xs:element name="QQDBData" type="QQDBData">
<xs:key name="PK-Orders">
<xs:selector xpath="Order"/>
<xs:field xpath="#Name"/>
</xs:key>
<xs:keyref name="FK-PrintoutSettings" refer="PK-Orders">
<xs:selector xpath="PrintoutSettings"/>
<xs:field xpath="#OrderSource"/>
</xs:keyref>
</xs:element>
The answer you've got from #DevNull is technically correct (+1); it is, however, not so much XSD; have a look at this section from the schema primer to understand the limitations you have with ID/IDREF.
I'll take the schema put forward by DevNull and modify it to show you the recommended XSD approach that relies on key/keyref.
UPDATE: I took your schema and updated to make sure it is sufficient for my tests:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:complexType name="Order">
<xs:sequence>
<xs:element form="qualified" minOccurs="0" name="Documents" type="Documents"/>
</xs:sequence>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="Translator" type="xs:string" use="required"/>
<xs:attribute name="Proofreader" type="xs:string" use="required"/>
<xs:attribute name="LockedBy" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="Documents"/>
<xs:complexType name="Orders">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Order" type="Order"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="QQDBData">
<xs:sequence>
<xs:element minOccurs="0" name="Orders" type="Orders"/>
<xs:element minOccurs="0" name="LocalSettings" type="Settings"/>
</xs:sequence>
<xs:attribute default="2000-01-01" name="CreationDate" type="xs:date" use="optional"/>
</xs:complexType>
<xs:complexType name="Settings">
<xs:attribute name="OrderSource" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="QQDBData" type="QQDBData">
<xs:key name="PK-Orders">
<xs:selector xpath="Orders/Order"/>
<xs:field xpath="#Name"/>
</xs:key>
<xs:keyref name="FK-PrintoutSettings" refer="PK-Orders">
<xs:selector xpath="LocalSettings"/>
<xs:field xpath="#OrderSource"/>
</xs:keyref>
</xs:element>
</xs:schema>
What I had to do is to update the selectors, since by introducing additional tags, the XPath has changed. I always try to visualize the constraints, to ensure that the XPaths as described still make sense.
An updated sample XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<QQDBData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" CreationDate="2000-01-01">
<Orders>
<Order Name="Name1" Translator="Translator1" Proofreader="Proofreader1" LockedBy="LockedBy1">
<Documents/>
</Order>
<Order Name="Name1" Translator="Translator1" Proofreader="Proofreader1" LockedBy="LockedBy1">
<Documents/>
</Order>
</Orders>
<LocalSettings OrderSource="OrderSource1"/>
</QQDBData>
An error message, for the same invalid XML may look like (I am using QTAssistant to validate):
Error occurred while loading [], line 12 position 3
The key sequence 'OrderSource1' in Keyref fails to refer to some key.
You can use an attribute type of xs:ID for <Order> and an attribute type of xs:IDREF for <PrintoutSettings>.
Example XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="doc">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="Order"/>
<xs:element ref="PrintoutSettings"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Order">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:NMTOKEN">
<xs:attribute name="Name" use="required" type="xs:ID"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="PrintoutSettings">
<xs:complexType>
<xs:attribute name="OrderSource" use="required" type="xs:IDREF"/>
</xs:complexType>
</xs:element>
</xs:schema>
Example of INVALID XML: (Gives the error "There is no ID/IDREF binding for IDREF 'NameOfOrder_X'." in Xerces.)
<doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="book.xsd">
<Order Name="NameOfOrder">...</Order>
<Order Name="NameOfOrder2">...</Order>
<PrintoutSettings OrderSource="NameOfOrder_X"/>
</doc>
Example of VALID XML:
<doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="book.xsd">
<Order Name="NameOfOrder">...</Order>
<Order Name="NameOfOrder2">...</Order>
<PrintoutSettings OrderSource="NameOfOrder2"/>
</doc>
For the following xml need a schema.
<?xml version="1.0" encoding="UTF-8"?>
<overall_operation>
<operation type="list_products">
<ops_description>Listing all the products of a company</ops_description>
<module>powesystem</module>
<comp_name>APC</comp_name>
<prod_price>50K$</prod_price>
<manf_date>2001</manf_date>
<pool_name>Electrical</pool_name>
<fail_retry>2</fail_retry>
<storage_type>avialble</storage_type>
<storage_check>false</storage_check>
<api_type>sync</api_type>
<product_name>transformer</product_name>
</operation>
<operation type="search_product">
<ops_description>Search the products of a company from the repository</ops_description>
<module>high-voltage</module>
<module>powesystem</module>
<comp_name>APC</comp_name>
<pool_name>Electrical</pool_name>
<fail_retry>2</fail_retry>
<storage_type>avialble</storage_type>
<storage_check>false</storage_check>
<api_type>sync</api_type>
<product_name>setup-transformer</product_name>
</operation>
</overall_operation>
Here different elements with operation like list_products,search_products and so on.
Each element will have some common attributes such as ops_description,module and so on.
Also some of the unique attributes for each element such as prod_price,manf_date etc.
I want to have a xml schema to validate. Some of the attributes also optional.
I tried using abstract and derived but could not make it work.
What you want to achieve is not possible with xml schema. The definition states that every element or attribute must be validated on its own and without reference to other elements or attributes.
The best solution you can get is to group optional but dependent elements:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="overall_operation">
<xs:complexType>
<xs:sequence>
<xs:element name="operation" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="ops_description" />
<xs:element name="module" minOccurs="1" maxOccurs="2" />
<xs:element name="comp_name" />
<xs:group ref="price_and_date" minOccurs="0" maxOccurs="1" />
<xs:element name="pool_name" />
<xs:element name="fail_retry" />
<xs:element name="storage_type" />
<xs:element name="storage_check" />
<xs:element name="api_type" />
<xs:element name="product_name" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="price_and_date">
<xs:sequence>
<xs:element name="prod_price" />
<xs:element name="manf_date" />
</xs:sequence>
</xs:group>
</xs:schema>
Use minOccurs and maxOccurs attributes to control optional elements and groups.