Consider the following XSD code...
<xs:group name="foo.cnt">
<xs:choice>
<xs:group ref="blah"/>
</xs:choice>
</xs:group>
<xs:element name="foo">
<xs:complexType mixed="true">
<xs:complexContent mixed="true">
<xs:extension base="foo.class">
<xs:attribute ref="bar" default="sample"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:complexType name="foo.class" mixed="true">
<xs:sequence>
<xs:group ref="foo.content"/>
</xs:sequence>
<xs:attributeGroup ref="foo.attributes"/>
</xs:complexType>
<xs:group name="foo.content">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="foo.cnt" minOccurs="0"/>
</xs:choice>
</xs:sequence>
</xs:group>
I'm trying to create a redefine (in a separate XSD) to add a string length restriction...
<xs:restriction base="xs:string">
<xs:length value="8"/>
</xs:restriction>
I keep getting parsing errors every way that I've tried. Where/how can I add the restriction?
Thanks!
Related
I have a following schema (1.1). I would like to have schema that will check that a sequence of parameters has mendatory parameter of type '1' and optional parameter of type '2'. I did it using alternatives because different types have different list of attributes.
How write an assertion to check that parameter of type 1 is mendatory?
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified" vc:minVersion="1.1">
<xs:element name="rule">
<xs:complexType>
<xs:sequence>
<xs:element name="conditions" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="condition" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="parameter" maxOccurs="unbounded" minOccurs="1">
<xs:alternative test="#type = '1'" type="typeOne"/>
<xs:alternative test="#type = '2'" type="typeTwo" />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="typeOne">
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="typeTwo">
<xs:attribute name="type" type="xs:string" use="required" />
</xs:complexType>
</xs:schema>
I did it using alternatives because different types have different list of attributes.
It would be like this:
<xs:element name="condition" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="parameter" maxOccurs="unbounded" minOccurs="1">
<xs:alternative test="#type = '1'" type="typeOne"/>
<xs:alternative test="#type = '2'" type="typeTwo" />
</xs:element>
</xs:sequence>
<xs:assert id="type-1-mandatory" test="parameter[#type eq '1']"></xs:assert>
</xs:complexType>
</xs:element>
I have an XML that supplies a Reference number. It should have either HeaderNumber and LineNumber OR ExternalReference. Both (all three elements) are allowed as well.
I can get the first part right with groups and a choice, but how do I allow (and not force) for all elements to be present?
I have this XSD to force all elements to be present:
<xs:schema>
<xs:group name="InternalReference">
<xs:all>
<xs:element name="HeaderNumber" type="xs:int"/>
<xs:element name="LineNumber" type="xs:int"/>
</xs:all>
</xs:group>
<xs:group name="Reference">
<xs:all>
<xs:group ref="InternalReference"/>
<xs:element name="ExternalReference"/>
</xs:all>
</xs:group>
<xs:complexType name="message">
<xs:all>
<xs:group ref="Reference" minOccurs="1"/>
</xs:all>
</xs:complexType>
<xs:element name="Message" type="message"/>
</xs:schema>
and this XSD to have either of the references present:
<xs:schema>
<xs:group name="InternalReference">
<xs:sequence>
<xs:element name="HeaderNumber" type="xs:int"/>
<xs:element name="LineNumber" type="xs:int"/>
</xs:sequence>
</xs:group>
<xs:group name="Reference">
<xs:choice>
<xs:group ref="InternalReference"/>
<xs:element name="ExternalReference"/>
</xs:choice>
</xs:group>
<xs:complexType name="message">
<xs:sequence>
<xs:group ref="Reference" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Message" type="message"/>
</xs:schema>
I would appreciate any help very much.
I have a workaround. It's not the optimum solution, but very workable.
<xs:schema>
<xs:element name="ExternalReference" type="xs:string"/>
<xs:group name="InternalReference">
<xs:sequence>
<xs:element name="HeaderNumber" type="xs:int"/>
<xs:element name="LineNumber" type="xs:int"/>
<xs:element ref="ExternalReference" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:group>
<xs:group name="External">
<xs:sequence>
<xs:element ref="ExternalReference" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:group>
<xs:group name="Reference">
<xs:choice>
<xs:group ref="InternalReference"/>
<xs:group ref="External"/>
</xs:choice>
</xs:group>
<xs:complexType name="message">
<xs:sequence>
<xs:group ref="Reference" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Message" type="message"/>
</xs:schema>
I'm still hoping for a better way.
Hi again SO community,
got another request regarding how to define an XSD schema correctly.
Given I have an XML file like:
<?xml version="1.0" encoding="UTF-8" ?>
<transformation xmlns="http://www.denktmit.de/pdi/ktr" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.w3.org/2001/XMLSchema-instance
./test.xsd">
<info>
<name>TrafoName</name>
<description>TrafoDescription</description>
</info>
<changedby>LastUser</changedby>
<step>
<type>FileInput</type>
<description>FileInput Step description</description>
<FileInputParameterOne>FileInputParam</FileInputParameterOne>
<another>1</another>
</step>
<step>
<type>Select</type>
<description>Select Step description</description>
<SelectParameterOne>SelectParameterOne</SelectParameterOne>
<SelectParameterTwo>SelectParameterTwo</SelectParameterTwo>
<another>2</another>
</step>
</transformation>
This resembles the style of the transformation files as produced by http://community.pentaho.com/projects/data-integration/
As you can see, each step contains several sequence nodes on top
<type>Select</type>
<description>Select Step description</description>
and on bottom:
<another>2</another>
In between, arbitrary complex xml subtrees may occur. But what exactely max occur is determined by the value in "type". The use case is to store specific configurations for concrete Java classes, that all implement an interface, defining getters/setter for "type", "description" and "another" and defining addtional object structure themself. It would also be sufficient to neglect the order, as long as all the elements, needed for a specific class are somehow present.
I already read:
How to group types & subtypes in XSD
xsd: How to extend a type with an unordered list of elements
Use <xs:all> in XML schema's complexType?
xsd: How to extend a type with an unordered list of elements
And I tried something like
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.denktmit.de/pdi/ktr" elementFormDefault="qualified"
attributeFormDefault="unqualified" xmlns="http://www.denktmit.de/pdi/ktr">
<xs:element name="transformation">
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="step" type="fileInputStep"></xs:element>
<xs:element name="step" type="selectStep"></xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="stepComplexType" abstract="true"></xs:complexType>
<xs:complexType name="fileInputStep">
<xs:complexContent>
<xs:extension base="stepComplexType">
<xs:sequence>
<xs:element name="type" minOccurs="1"
maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string"></xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="description" type="xs:string"
minOccurs="1" maxOccurs="1"></xs:element>
<xs:element name="FileInputParameterOne" type="xs:string">
</xs:element>
<xs:element name="another" type="xs:int" minOccurs="1"
maxOccurs="1"></xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="selectStep">
<xs:complexContent>
<xs:extension base="stepComplexType">
<xs:sequence>
<xs:element name="type" minOccurs="1"
maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="Select"></xs:pattern>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="description" type="xs:string"
minOccurs="1" maxOccurs="1"></xs:element>
<xs:element minOccurs="1" name="SelectParameterOne"
type="xs:string">
</xs:element>
<xs:element minOccurs="1" name="SelectParameterTwo"
type="xs:string">
</xs:element>
<xs:element name="another" type="xs:int" minOccurs="1"
maxOccurs="1"></xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
But it is not working, telling me:
Multiple annotations found at this line: validation against this
schema, ambiguity would be created for those two particles.
- Start tag of element
- cos-element-consistent: Error for type '#AnonType_transformation'. Multiple elements with name 'step', with different types, appear in
the model group.
Any ideas?
You may use xsd Group. Here's an sample for your reference
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="transformation">
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="step" type="stepType"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="stepComplexType" abstract="true"></xs:complexType>
<xs:group name="selectParamGroup">
<xs:sequence>
<xs:element name="SelectParameterOne" type="xs:string" minOccurs="1" maxOccurs="1">
</xs:element>
<xs:element name="SelectParameterTwo" type="xs:string" minOccurs="1" maxOccurs="1">
</xs:element>
</xs:sequence>
</xs:group>
<xs:group name="paramGroup">
<xs:choice>
<xs:element name="FileInputParameterOne" type="xs:string">
</xs:element>
<xs:group ref="selectParamGroup">
</xs:group>
</xs:choice>
</xs:group>
<xs:complexType name="stepType">
<xs:complexContent>
<xs:extension base="stepComplexType">
<xs:sequence>
<xs:element name="type" minOccurs="1"
maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string"></xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="description" type="xs:string"
minOccurs="1" maxOccurs="1"></xs:element>
<xs:group ref="paramGroup"></xs:group>
<xs:element name="another" type="xs:int" minOccurs="1"
maxOccurs="1"></xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<transformation>
<step>
<type>FileInput</type>
<description>FileInput Step description</description>
<FileInputParameterOne>FileInputParam</FileInputParameterOne>
<another>1</another>
</step>
<step>
<type>Select</type>
<description>Select Step description</description>
<SelectParameterOne>SelectParameterOne</SelectParameterOne>
<SelectParameterTwo>SelectParameterTwo</SelectParameterTwo>
<another>2</another>
</step>
</transformation>
I would like to write a XSD element that permit something like that :
<CustomFields>
<CustomField id="1">some text data</CustomField>
<CustomField id="2">some text data</CustomField>
</CustomFields>
But I have some restrictions : I have to restrict the text (maxLenght = 36). And I would like to be impossible to have 2 CustomField with the same id.
So far I wrote this, but it not what I want :
<xs:element name="CustomFields" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomField" minOccurs="0" maxOccurs="20">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:integer" use="required"></xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Thanks for any help.
Regards.
You could use following attempt
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="restrictedString">
<!-- Make a new type to be a "descendant" of string-->
<xs:restriction base="xs:string">
<xs:maxLength value="36"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="CustomFields">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomField" minOccurs="0" maxOccurs="20">
<xs:complexType>
<xs:simpleContent>
<!-- reference new type you declared above -->
<xs:extension base="restrictedString">
<xs:attribute name="id" type="xs:integer" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!-- Restrict #id to be unique-->
<xs:unique name="id_uq">
<xs:selector xpath="CustomField"/>
<xs:field xpath="#id"/>
</xs:unique>
</xs:element>
</xs:schema>
I am try to create an xsd schema that validates the following xml:
<results>
<row>
<PersonID key="true">1</PersonID>
<FirstName>John</FirstName>
<Surname>Smith</Surname>
<LogonName>jsmith</LogonName>
</row>
<row>
<PersonID key="true">2</PersonID>
<FirstName>Steve</FirstName>
<Surname>Jones</Surname>
<LogonName>sjones</LogonName>
</row>
The results node and row node are mandatory, but the nodes inside each row are optional and may have other nodes that I have not listed. There could 1 row or many rows.
I have created the below but I am unable to validate correctly:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:choice minOccurs="0">
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
Thanks.
If PersonID, FirstName etc. can occurr at most once - and in that specific order - try this:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
(basically just drop the choice element). If PersonID, FirstName etc. can occurr at most once but in any order you can use all:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:all>
<xs:element name="PersonID" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:byte">
<xs:attribute type="xs:string" name="key" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="FirstName" minOccurs="0"/>
<xs:element type="xs:string" name="Surname" minOccurs="0"/>
<xs:element type="xs:string" name="LogonName" minOccurs="0"/>
<xs:element type="xs:string" name="GroupName" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
If you don't know elements can occur within row you can use:
<xs:element name="results">
<xs:complexType>
<xs:sequence>
<xs:element name="row" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
that accepts any element within row.