XSD : restrict many different attributes that take the same values - attributes

I want to do this:
XML Schema How to Restrict Attribute by Enumeration
...but I have MANY different attributes that take the exact same values. This makes my XSD very complex.
Can I define the restriction once and then reference it on each attribute somehow ???
Thanks in advance. :)

If you have many different attributes that take on the exact same values, simply reuse the attribute type definitions:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">
<xs:simpleType name="colorType">
<xs:restriction base="xs:string">
<xs:enumeration value="red" />
<xs:enumeration value="green" />
<xs:enumeration value="blue" />
</xs:restriction>
</xs:simpleType>
<xs:element name="RoomColors">
<xs:complexType>
<xs:attribute name="wall" type="colorType"/>
<xs:attribute name="carpet" type="colorType"/>
<xs:attribute name="ceiling" type="colorType"/>
<xs:attribute name="funiture" type="colorType"/>
</xs:complexType>
</xs:element>
</xs:schema>
It's when the values are not the exact same that there's more creativity involved. See Extend enumerated lists in XML schema.

Related

xs:attribute type attribute vs xs:simpleType xs:restriction base attribute

I'm looking at an auto-generated XSD and I noticed that there are quite a few types that are repeated & so am looking to minimize repetition. When I write my own XSDs I normally do it the way its done for the Option1 attribute in the code below, however this XSD does it the way that the Option2 attribute is done.
<xs:element name="baseElement">
<xs:complexType>
<xs:attribute name="Option1" type="NonEmptyString" />
<xs:attribute name="Option2">
<xs:simpleType>
<xs:restriction base="NonEmptyString" />
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:simpleType name="NonEmptyString">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
So I was wondering, is there a difference between these two methods & if not which is better practice? I would be more inclined to use Option1 as it makes the overall file shorter easier to manage

Uploading XSD schemas with imported namespaces into Marklogic 6

As a small excercise I'm trying to upload and validate documents with a couple of schemas. These will eventually grow so I'd like to keep them separate.
These example schemas define a localized text string and a food dish:
bitfood-common.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:bfc="http://bitfood.org/common"
targetNamespace="http://bitfood.org/common"
elementFormDefault="qualified">
<xs:simpleType name="objectId">
<xs:restriction base="xs:string">
<xs:length value="24"/>
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="locale">
<xs:restriction base="xs:string">
<xs:length value="5"/>
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="localizedText">
<xs:attribute name="text" type="xs:string" use="required"/>
<xs:attribute name="locale" type="bfc:locale" use="required"/>
</xs:complexType>
</xs:schema>
bitfood-dish.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:bfd="http://bitfood.org/dish"
xmlns:bfc="http://bitfood.org/common"
targetNamespace="http://bitfood.org/dish"
elementFormDefault="qualified">
<xs:import namespace="http://bitfood.org/common"
schemaLocation="../common/bitfood-common.xsd" />
<xs:element name="Dish">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="bfc:localizedText" maxOccurs="unbounded"/>
<xs:element name="description" type="bfc:localizedText" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="id" type="bfc:objectId" use="required"/>
<xs:attribute name="price" type="xs:decimal" use="required"/>
<xs:attribute name="imageUrl" type="xs:anyURI" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
I then uploaded these two documents inside the Schemas database assigned to my xml database with the following URI id's:
schema/common/bitfood-common.xsd
schema/dish/bitfood-dish.xsd
And then I uploaded an example document:
dish/520cc720c208c01ddfb75254.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Dish id="520cc720c208c01ddfb75254" price="35"
imageUrl="FoodCantonGourrmetTwoDish.jpg"
xmlns="http://bitfood.org/dish">
<name text="Example dish." locale="en-US"/>
<description text="Localized text test." locale="en-US"/>
</Dish>
When I issue the following command on the server's query console, I get the empty set when I instruct the database to infer the type of the xml document's root node:
Update: wrong node index, must be 1 in this case:
(: is it working? :)
declare namespace bfd = "http://bitfood.org/dish";
declare namespace bfc = "http://bitfood.org/common";
xdmp:describe(data(
doc('dish/520cc720c208c01ddfb75254.xml')/bfd:Dish[1]
))
Output:
<?xml version="1.0" encoding="UTF-8"?>
<results warning="atomic item">xs:untypedAtomic("")</results>
This means that the database is either ignoring or not able to find my schema documents. Also, I am not sure if it can't apply the schemas because of the xs:import namespace statement.
Has anyone attempted to work with imported XSD documents into Marklogic in this way? Is there anything I may be doing wrong?
Update 2: It seems this can only be applied to attributes. The following command does work as expected, which means the schemas are being detected:
(: is it working? :)
declare namespace bfd = "http://bitfood.org/dish";
declare namespace bfc = "http://bitfood.org/common";
xdmp:describe(data(doc('dish/520cc720c208c01ddfb75254.xml')/bfd:Dish[1]/#id))
Thanks!
XQuery positional predicates start at 1 not 0.
Try this:
doc('dish/520cc720c208c01ddfb75254.xml')/bfd:Dish[1]
Then work your way up to more complicated code.
-David Lee

XSD: restrict attribute to xs:float or ""

I'm trying to define an element type in XSD, for which i want an optional attribute, which if present can either contain a float, or be empty (but still present).
i.e:
<xs:element name="MyElement">
<xs:complexType>
<xs:attribute name="optionalFloatAttribute" type="xs:float" use="optional"/>
</xs:complexType>
</xs:element>
Needs "fixing" to allow all of the following xml:-
<MyElement/>
or
<MyElement optionalFloatAttribute=""/>
or
<MyElement optionalFloatAttribute="3.14159"/>
The only way I can see of doing this is to change type to xs:string, and use xs:restriction with a regular expression. But this doesn't seem very ideal to me. Is there a better way?
And I have to be able to support these variations of the xml - the program and existing xml is legacy, and I am trying to back-create a schema to match the myriad variations I see in what we have to regard as valid xml.
You can define custom type for that by combining float and empty string:
<xs:element name="MyElement">
<xs:complexType>
<xs:attribute name="optionalFloatAttribute" type="emptyFloat" use="optional"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="emptyFloat">
<xs:union>
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:length value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base='xs:float'>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
Or using regExp:
<xs:simpleType name="emptyFloat">
<xs:restriction base="xs:string">
<xs:pattern value="-?\d*\.?\d*"/>
</xs:restriction>
</xs:simpleType>
If you could stand using an element rather than an attribute you could make the xs:float nillable. This way you can use the xsi:nil="true" in your instance document to indicate that the element has no value:
<!-- definition -->
<xs:element name="quantity" type="xs:float" nillable="true" />
<!-- instance -->
<quantity xsi:nil="true" />
No equivalent for attributes though.
I don't think there's a way to handle this and use xs:float. Fundamentally it comes down to the fact that empty string isn't a valid number. You'd either normally expect a value of 0, or for the element to be missing altogether. There's a good explanation as the answer to the following question:
Empty elements for primitve datatypes forbidden in XSD
It seems that the option of using xs:string and a regexp might be your best plan.

XSD any element

I'm trying to create a list that some of the elements are defined and some are not, without priority to order.
I tried it this way, with an any element:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="object" mixed="true">
<xs:choice>
<xs:element name="value" minOccurs="1" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:any namespace="##any" processContents="skip"/>
</xs:choice>
</xs:complexType>
<xs:element name="object" type="object"/>
</xs:schema>
And it tells me this error:
:0:0: error: complex type 'object' violates the unique particle
attribution rule in its components 'value' and '##any'
Can someone help me out solve the problem?
You cannot define your schema like that, it violates the unique particle attribution rule: the parser cannot tell whether a "value" element it finds in the document should be validated against "value" or against "any".
Here is a good overview.
Consider using two namespaces and using xsd:any with a namespace, this will remove the problem.

How to validate empty string value tag in xsd

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>

Resources