Is it possible to define an XML Schema (XSD) to correctly describe a document such as the following?
<root>
<str name="status">success</str>
<str name="message">Your request has been processed successfuly.</str>
</root>
The problem might be that the <str> tags have an attribute (name) as well as string values.
I would be grateful if anyone could come up with an XML Schema for this piece of XML, since I am kind of stuck at this point. My best attempt so far is shown below, but botice that the <str> element cannot have a type (such as xsd:string) in this context.
<xs:element name="object">
<xs:complexType>
<xs:sequence>
<xs:element name="str" minOccurs="2" maxOccurs="2">
<xs:complexType>
<xs:sequence>
<xs:element name="productName" type="xs:string"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Your constraints are not entirely clear, so a number of schemas would validate the XML depending on how loose/tight you would want the validation to be. This example shows a schema that mandates exactly two elements inside the element and they must have a "name" attribute with the values "status" or "message".
<?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="str" type="StrType" minOccurs="2" maxOccurs="2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="StrType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="StrAttribute" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="StrAttribute">
<xs:restriction base="xs:string">
<xs:enumeration value="status"/>
<xs:enumeration value="message"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Of course, this would allow two elements both with the name attribute set to "message", or with "message" first, then status. I believe the schema cannot define a sequence containing two elements of the same name but different types which you would need if you required the validation to ensure that the first always contained "status" and the second one contained "message".
Related
I am having trouble getting this XML file to validate against my schema, which doesn't have syntax errors according to my XML editor. I am trying to make course an complexType element, but it keeps telling me I can't. The XML is correct, it is definitely something with my schema, I just can't figure it out.
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<courses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="course_offerings.xsd">
<course id="WEB225">
<name>Web Development II</name>
<offered>Spring</offered>
<pre_reqs>WEB125</pre_reqs>
</course>
<course id="WEB125">
<name>Web Development I</name>
<offered>Fall</offered>
</course>
<course id="WEB325">
<name>Client-Side Scripting</name>
<offered>Spring</offered>
<offered>Fall</offered>
<pre_reqs>WEB225</pre_reqs>
</course>
</courses>
And here is my schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="courses">
<xs:complexType>
<xs:sequence>
<xs:element name="course" type="xs:string"/>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="offered" type="xs:string"/>
<xs:element name="pre_reqs" type="xs:string"/>
</xs:sequence>
</xs:sequence>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
Since you haven't mentioned what error you are getting, I'm providing what I can observe..
In your XML you have included this statement: xsi:noNamespaceSchemaLocation="course_offerings.xsd" This means it is your default XML schema. You need to verify the name of schema and make sure it is present in default path.. (same as that of XML file). Otherwise you may end up seeing an error unable to locate schema
course_offerings.xsd
You have declared <xs:element name="course" type="xs:string"/> as string .. that should not be the case.. In your XML it's a complexType, ie, an element having child elements inturn..
All these elements name, offered, pre_reqs should come under this complexType
Attribute should be within the scope of this complexType..
Otherwise you would face not just one but multiple errors since the definition of element course is invalid
Refer the sample XSD below:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="courses">
<xs:complexType>
<xs:sequence>
<xs:element name="course">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="offered" type="xs:string"/>
<xs:element name="pre_reqs" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The above mentioned style is hierarchical, there is an alternative method to write a schema file.. If you understand the current consequences and if you wish to know further then I will let you know..
For now this much explanation should be good..
please assist, this is what i want to achieve in validating my xml file:
<?xml version="1.0" encoding="UTF-8"?>
<worker>
<name>dingo</name>
<ssn>12345</ssn>
</worker>
I want to ensure that the two simple elements 'name' and 'ssn' either have values (as a group) or do not have any value (as a group). They cannot exist individually with a value.
I have to use an XSD schema, so cannot use other options i see suggestions sometimes: Relax NG etc.
I looked into creating a group for elements 'name' and 'ssn' but i am unable to find out how to create a restriction for this group to obtain my condition.
My current XSD file:
<xs:complexType name="worker">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" "maxOccurs="1">
<xs:element name="ssn" type="xs:positiveInteger" minOccurs="0" "maxOccurs="1">
</xs:sequence>
</xs:complexType>
<xs:complexType name="worker">
<xs:sequence minOccurs="0">
<xs:element name="name" type="xs:string">
<xs:element name="ssn" type="xs:positiveInteger">
</xs:sequence>
</xs:complexType>
You have to do
<xs:complexType name="worker">
<xs:group ref="workerGrp" minOccurs="0"/>
</xs:complexType>
<xs:group name="workerGrp">
<xs:sequence>
<xs:element name="name" type="xs:string">
<xs:element name="ssn" type="xs:positiveInteger">
</xs:sequence>
</xs:group>
I'm falling over on a frustrating, arbitrary restriction in XML Schema. For some reason, it insists that PK-FK relationships have to be one-to-one. Why?
For example, given the schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="FutureSchema"
targetNamespace="http://tempuri.org/FutureSchema.xsd"
elementFormDefault="unqualified"
xmlns="http://tempuri.org/FutureSchena.xsd"
xmlns:mstns="http://tempuri.org/FutureSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FUTUREFILE">
<xs:complexType>
<xs:sequence>
<xs:element name="Configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="Experiments">
<xs:complexType>
<xs:sequence>
<xs:element name="Experiment">
<xs:complexType>
<xs:attribute name="ID" type="xs:integer"/>
<xs:attribute name="Profile" type="xs:integer"/>
</xs:complexType>
<xs:keyref name="dummy" refer="LP">
<xs:selector xpath="Experiment"/>
<xs:field xpath="#Profile"/>
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:key name="LP">
<xs:selector xpath="*/Configuration/Profiles/Profile"/>
<xs:field xpath="#ID"/>
</xs:key>
</xs:element>
<xs:element name="Profiles">
<xs:complexType>
<xs:sequence>
<xs:element name="Profile">
<xs:complexType>
<xs:attribute name="ID" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And an example instance:
<?xml version="1.0" encoding="utf-8" ?>
<b:FUTUREFILE xmlns:b="http://tempuri.org/FutureSchena.xsd">
<Configuration>
<Experiments>
<Experiment ID="1" Profile="1"/>
<Experiment ID="2" Profile="1"/>
</Experiments>
<Profiles>
<Profile ID="1"/>
</Profiles>
</Configuration>
</b:FUTUREFILE>
Document validation throws an error if I define <Experiment ID="1" FK="1"/><Experiment ID="2" FK="1"/>, for example; i.e. more than one Experiment may not reference the same Profile. But why else would I want to use a key relationship? What use is a key relationship at all if I can't do something so fundamental?
OK, if and won't let me do this, how should I?
edit #1: As requested, I've padded out my code sample to include the full schema and a basic instance.
edit #2: Interesting. SharpDevelop's XML editor (as opposed to Visual Studio's) doesn't seem to object. It doesn't object to the foreign key value referring to a nonexistent primary key either (which IMO it should) but it's a start.
What wasn't clear ?... My english, it's all :-)
Some remarqs, I'm not sure it's solution :
In exemple instance, it's best to use xmlns:b="http://tempuri.org/FutureSchema.xsd">, and not xmlns:b="http://tempuri.org/FutureSchena.xsd"> (n -> m).
Also it's best to put b: in front of all elements names.
According to your schema, you can't have two Experiment in Experiments, only one.
On xsd, put <xs:keyref name="dummy" refer="mstns:LP">, that works best for me ; it's because xpath expression doesnt't understand default namespace, see Correct way to use key in xsd.
I have following XML schema:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="content" type="contentType"/>
<xs:complexType name="contentType">
<xs:complexContent>
<xs:extension base="versionedElementType">
<xs:sequence>
<xs:element name="item" type="itemType" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="itemType" mixed="true">
<xs:complexContent>
<xs:extension base="itemTypeBase">
<xs:sequence>
<xs:element name="order" type="xs:unsignedInt"/>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- Simple type convert to complex type -->
<xs:complexType name="itemTypeBase" mixed="true">
<xs:simpleContent>
<xs:extension base="itemDescriptionType">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<!-- Simple type -string restriction -->
<xs:simpleType name="itemDescriptionType" >
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="versionedElementType">
<xs:attribute name="version" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
which I use to validate this XML instance (I want to mix the text in the 'item' element with sub-elements 'order' and 'id'):
<?xml version="1.0" encoding="UTF-8"?>
<content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Content.xsd"
version ="1.0">
<item>Description here...
<order>2</order>
<id>2</id>
</item>
</content>
Whatever I did the validation still says taht there is an error:
The content type of a derived type and that of its base must both be mixed or both be element-only. Type 'itemType' is mixed, but its base type is not.
But I can see that both types - itemType and itemTypeBase are MIXED!!
Thanks a lot
STeN
First of all the error which I see if I open your schema in Visual Studio 2010 is:
The derived type and the based type
must have the same content type.
In you current schema the type itemTypeBase is defined with respect of the <xs:simpleContent> and derived type itemType with the respect of <xs:complexContent> which is not allowed. Either you allow no sub-elements and use <xs:simpleContent> or you do use child elements and use <xs:complexContent>.
I personally don't like and don't use mixed types. If I understand you correct you want to make some restrictions in the text from the content. You want to have the content length between 1 and 64 characters. But <order>2</order>, <id>2</id> and all whitespace, inclusive the new line characters, are also a part of the content. If you want that <item> has simple content, then you can not insert child elements inside.
So the pragmatical solution would be go away from the mixed model and use the XML document in the form
<?xml version="1.0" encoding="utf-8"?>
<content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Content.xsd"
version ="1.0">
<item>
<description>Description here...</description>
<order>2</order>
<id>2</id>
</item>
</content>
where Content.xsd is
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="content" type="contentType"/>
<xs:complexType name="contentType">
<xs:sequence>
<xs:element name="item" type="itemType"
minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="version" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="itemType">
<xs:sequence>
<xs:element name="description" type="itemDescriptionType"/>
<xs:element name="order" type="xs:unsignedInt"/>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="itemDescriptionType" >
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
All will be very simple and clear.
I have an xml file which is having some date values and other datatypes.
<Purchasedate Name="purcaseDate" value=""/>
I am validating these xml files with a xsd file.
In xsd shcema I have written a regular expression pattern for dd/mm/yyyy format.
This is working fine if value attribute have a value.
My pattern is validating against the value attribute.
The field (purchasedate) is not mandatory.
if value="", this means my pattern is validating against an empty string also, which is not mandatory.
I need to validate the optional field
and i am using <xs:attribute name="PurchaseDate" use="optional"> also.
I need to validate this field when value tag is not empty.
That's too easy ..
Just all you have to do is to include empty string specification in your pattern
This is the way to do that ..
<xs:pattern value="|(Regular_pattern_goes_here)"/>
For your reference I have written a sample chunks of codes .. just go through them ..
sample XML:
<?xml version="1.0" encoding="utf-8"?>
<xmln xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com XMLFile1.xsd" xmlns="http://www.xsdef.com/xml/123">
<Purchasedate Name="purcaseDate" value=""/>
</xmln>
sample XSD:(includes custom type def)
<xs:schema xmlns:xsLocal="http://www.xsdef.com/xml/123" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.xsdef.com/xml/123" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="xmln">
<xs:complexType>
<xs:sequence>
<xs:element name="Purchasedate">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="value" type="xsLocal:CUSTOM_DATE" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="CUSTOM_DATE">
<xs:restriction base="xs:string">
<xs:pattern value="|((01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)/(01|02|03|04|05|06|07|08|09|10|11|12)/[1-2][0-9][0-9][0-9])"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
try adding this attribute nillable="true" into the xml tag definition
Also you can take a look at his link http://www.zvon.org/xxl/XMLSchemaTutorial/Output/ser_over_st0.html
Best Reagds,
Iordan
The '?' character in the Regex means that the character before it must occur 0 or 1 times.
So in order to solve your issue you need to wrap the regex in parenthesis and put a questionmark at the end:
<xs:simpleType name="PurchaseDateType">
<xs:restriction base="xs:string">
<xs:pattern value="(Regular_pattern_goes_here)?"/>
</xs:restriction>
</xs:simpleType>
Use this type on your field and you should be fine
If you control the syntax of the XML, you should consider defining the element as follows. Since XML-Schema already provides a date type, you should use it unless you have a really good reason. I say this because it will make it easier for others to use the xml and for you to use better code frameworks later. I didn't include the "name" attribute because it seemed redundant to the element name.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="Purchasedate" nillable="true" type="xs:date"/>
<xs:element name="Purchasedate2">
<xs:complexType>
<xs:attribute name="value" type="xs:date"/>
</xs:complexType>
</xs:element>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="Purchasedate"/>
<xs:element minOccurs="0" ref="Purchasedate2"/>
</xs:sequence>
</xs:complexType>
</xs:element>