Set attribute to all types in XML Schema - xsd

I store settings of my script in XML document. The script is multiplatform but some of its settings are not. I created proper attribute in my XSD file. It decides to which system is the setting.
<xs:attribute name="system" use="optional" default="none">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="none"/>
<xs:enumeration value="windows"/>
<xs:enumeration value="unix"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
A sample XML file looks like below. (Don't read too carefully. It's just an example.)
<root>
<name>Foo</name>
<path system="windows">%appdata%\Bar</path>
<path system="unix">~/Bar/</path>
<foo system="unix">
<bar>baz</bar>
<!-- more elements -->
</foo>
<foo>
<bar system="windows">baz</bar>
<!-- more elements -->
</foo>
</root>
The problem is I need possibility to add attribute system to each element of my XML. At this moment I can't simply write:
<xs:element name="path" type="xs:string"/>
Instead that I have to write:
<xs:element name="path">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="system"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
(I know that I can define complex type before and use it multiple times.) It is very expanded XSD and I have a lot of my own types in it. Many of them are used in one place only. Actually I set attribute system to each type in my XSD but it takes a lot of space and is not very readable.
Is it possible to set attribute to all types in XSD?

Your options for globally defining a common attribute to be used in many locations include:
Have all types derive from a common type that includes the attribute.
Use xs:attribute/#ref, which you've already mentioned.
Use xs:attributeGroup/#ref, which would allow you to reference multiple
commonly declared attributes collectively. Update: In XSD 1.1, a default attribute
group can be specified via defaultAttributes on the xs:schema element that applies to all
complex type definitions. Thanks to #sergioFC for this good idea.
Use xs:any element, and then (in XSD 1.1) xs:assert about the attribute, but
then you lose most of the normal element and attribute declaration
facilities due to xs:any's intrinsic leniency.
Other than such indirect options, there is no mechanism in XSD for centrally stating that an attribute may/must be present on all elements.

Related

XSD what is the difference between attribute with type and attribute with restriction?

I am doing some xsd cleanup activity with limited knowledge on XSD. The file I have contains a complex element with two attribute defined, but differently.
<xs:attribute name="DecisioningRequestType"
type="xs:string"
use="required"/>
<xs:attribute name="ProcessingRequestType"
use="required">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:attribute>
Through when xml is created, both attribute contain a string value, but I am trying to understand what difference does it make when the attribute are defined with restriction? Isn't that I can define my second attribute similar to the first attribute shown above?
If it is same, I can bring a uniformity in defining the attributes in my XSD file through this cleanup.
Attribute with restriction means that the type of the attribute value is defined
inline, directly within the definition of the attribute itself.
That is used when, on one hand, the attribute type is something special (not just a base type) but, on other hand, it is used only for that attribute.
So, defining that type as a separate component would be redundant.
But in your case, the construct:
<xs:attribute name="ProcessingRequestType" use="required">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:attribute>
although is valid, actually doesn't restrict anything (it is an empty restriction).
So, it is equivalent to
<xs:attribute name="ProcessingRequestType" type="xs:string" use="required"/>
A true restriction would look something like this:
<xs:attribute name="ProcessingRequestType" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="typeA"/>
<xs:enumeration value="typeB"/>
<xs:enumeration value="typeC"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
That means that the attribute value is a string, however restricted to be only one from the list: "typeA", "typeB", "typeC".
The declaration of an attribute requires that the type of the attribute be specified; this can be done either with a type attribute giving the name of the type, or with an inline declaration of an anonymous type.
The use or non-use of the XSD restriction element is orthogonal to the difference between a type attribute and a simpleType child. In the case you give, the restriction is vacuous; the inline declaration could just as easily have taken the form
<xs:simpleType>
<xs:union memberTypes="xs:string"/>
</xs:simpleType>
You write both attribute contain a string value -- this is true enough, as far as it goes, but the two attributes do not have the same type: one is associated with type xs:string and the other with an anonymous type whose value and lexical spaces are the same as those of xs:string (because it was created by a vacuous restriction of xs:string). In some cases, that difference can be important.

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.

How to define a Constant in XSD

Is there a way to define a constant value and use that constant in the preceeding XSD? I have a common value I want to use for various xs:element tag's maxOccurs attributes. Like constants in other languages, I want to make the change in one place should the value backing MyConst were to ever change.
<!-- Can I do this? -->
<ConstantValue id="MyConst" value="10"/>
...
<xs:element name="sandwich_meat" type="xs:string" minOccurs="0" maxOccurs="MyConst"/>
<xs:element name="sandwich_name" type="xs:string" minOccurs="0" maxOccurs="MyConst"/>
You can try to define a simpleType with a restriction:
<xs:simpleType name="AConstantHere">
<xs:restriction base="xs:string">
<xs:enumeration value="CONSTANT_VALUE_HERE"/>
</xs:restriction>
</xs:simpleType>
It allows only one value.
No it is not allowed that way. However you can define your own type with a fixed value in it somewhere on top of your XSD (place dosen matters) and use that type for the elements.
It's not possible with plain schema, but maybe XML entities will do the trick?

How to declare a non-string element as having optional content in XML Schema

I have seen XML Schema element with attributes containing only text but I have an element that's an xs:dateTime instead.
The document I'm trying to write a schema for looks like this:
<web-campaigns>
<web-campaign>
<id>1231</id>
<start-at nil="true"/>
</web-campaign>
<web-campaign>
<id>1232</id>
<start-at>2009-08-08T09:00:00Z</start-at>
</web-campaign>
</web-campaigns>
Sometimes the xs:dateTime element has content, sometimes it doesn't.
What I have so far (which doesn't validate yet) is:
<xs:element name="start-at">
<xs:complexType mixed="true">
<xs:simpleContent>
<xs:extension base="xs:dateTime">
<xs:attribute name="nil" default="false" type="xs:boolean" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
If I replace xs:dateTime with xs:string, I can validate the document just fine, but I really want an xs:dateTime, to indicate to consumers what's in that element. I tried with/without mixed="true" as well, to no avail.
If it makes a difference, I validate using xmllint (on Mac OS X 10.5) and XML Schema Validator
you can define your own types as union of types.
1/ define the "empty" type as a string that only allows "" ähm nothing :)
<xs:simpleType name="empty">
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
2/ next define a type that allows date AND empty
<xs:simpleType name="empty-dateTime">
<xs:union memberTypes="xs:dateTime empty"/>
</xs:simpleType>
3/ declare all your nullable datetime elements as type="empty-dateTime"
You need
<xs:element name="start-at" minOccurs="0">
mixed-mode isn't relevant to your situation, you don't need that. By default, minOccurs="1", i.e. the element is mandatory.
With minOccurs="0", you either specify the element with content, or not at all. If you want to be able to permit <start-at/>, then you cannot use xs:dateTime.

How do I create a reusable "US State" type in an XML schema?

I have an XML schema that includes multiple addresses:
<xs:element name="personal_address" maxOccurs="1">
<!-- address fields go here -->
</xs:element>
<xs:element name="business_address" maxOccurs="1">
<!-- address fields go here -->
</xs:element>
Within each address element, I include a "US State" enumeration:
<xs:simpleType name="state">
<xs:restriction base="xs:string">
<xs:enumeration value="AL" />
<xs:enumeration value="AK" />
<xs:enumeration value="AS" />
....
<xs:enumeration value="WY" />
</xs:restriction>
</xs:simpleType>
How do I go about writing the "US State" enumeration once and re-using it in each of my address elements? I apologize in advance if this is a n00b question -- I've never written an XSD before.
My initial stab at it is the following:
<xs:element name="business_address" maxOccurs="1">
<!-- address fields go here -->
<xs:element name="business_address_state" type="state" maxOccurs="1"></xs:element>
</xs:element>
I think you are on the right tracks. I think its more to do with XML namespaces. Try the following:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/foo"
xmlns:tns="http://www.example.org/foo"
elementFormDefault="qualified">
<xs:element name="business_address">
<xs:complexType>
<xs:sequence>
<xs:element name="business_address_state"
type="tns:state" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="state">
<xs:restriction base="xs:string">
<xs:enumeration value="AL" />
<xs:enumeration value="AK" />
<xs:enumeration value="AS" />
<xs:enumeration value="WY" />
</xs:restriction>
</xs:simpleType>
</xs:schema>
Note that the type is tns:state not just state
And then this is how you would use it:
<?xml version="1.0" encoding="UTF-8"?>
<business_address xmlns="http://www.example.org/foo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/foo foo.xsd ">
<business_address_state>AL</business_address_state>
</business_address>
Notice that this XML uses a default namespace the same as the targetNamespace of the XSD
While namespaces help keep schemas organized and prevent conflicts,
it's not the namespace above that allows for the reuse,
it's the placement of the type as an immediate child of the <xs:schema> root
that makes it a global type. (Usable within the namespace w/o the namespace qualifier and from anywhere that the tns namespace is visible w/ the tns: qualifier.)
I prefer to construct my schemas following the "Garden of Eden" approach, which maximizes reuse of both elements and types (and can also facilitate external logical referencing of the carefully made unique type/element from, say, a data dictionary stored in a database.
Note that while the "Garden of Eden" schema pattern offers the maximum reuse, it also involves the most work. At the bottom of this post, I've provided links to the other patterns covered in the blog series.
• The Garden of Eden approach http://blogs.msdn.com/skaufman/archive/2005/05/10/416269.aspx
Uses a modular approach by defining all elements globally and like the Venetian Blind approach all type definitions are declared globally. Each element is globally defined as an immediate child of the node and its type attribute can be set to one of the named complex types.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="TargetNamespace" xmlns:TN="TargetNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="BookInformation" type="BookInformationType"/>
<xs:complexType name="BookInformationType">
<xs:sequence>
<xs:element ref="Title"/>
<xs:element ref="ISBN"/>
<xs:element ref="Publisher"/>
<xs:element ref="PeopleInvolved" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeopleInvolvedType">
<xs:sequence>
<xs:element name="Author"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Title"/>
<xs:element name="ISBN"/>
<xs:element name="Publisher"/>
<xs:element name="PeopleInvolved" type="PeopleInvolvedType"/>
</xs:schema>
The advantage of this approach is that the schemas are reusable. Since both the elements and types are defined globally both are available for reuse. This approach offers the maximum amount of reusable content.
The disadvantages are the that the schema is verbose.
This would be an appropriate design when you are creating general libraries in which you can afford to make no assumptions about the scope of the schema elements and types and their use in other schemas particularly in reference to extensibility and modularity.
Since every distinct type and element has a single global definition, these canonical particles/components can be related one-to-one to identifiers in a database. And while it may at first glance seem like a tiresome ongoing manual task to maintain the associations between the textual XSD particles/components and the database, SQL Server 2005 can in fact generate canonical schema component identifiers via the statement
CREATE XML SCHEMA COLLECTION
http://technet.microsoft.com/en-us/library/ms179457.aspx
Conversely, to construct a schema from the canonical particles, SQL Server 2005 provides the
SELECT xml_schema_namespace function
http://technet.microsoft.com/en-us/library/ms191170.aspx
ca·non·i·cal
Related to Mathematics. (of an equation, coordinate, etc.)
"in simplest or standard form"
http://dictionary.reference.com/browse/canonical
Other, easier to construct, but less resuable/more "denormalized/redundant" schema patterns include
• The Russian Doll approach http://blogs.msdn.com/skaufman/archive/2005/04/21/410486.aspx
The schema has one single global element - the root element. All other elements and types are nested progressively deeper giving it the name due to each type fitting into the one above it. Since the elements in this design are declared locally they will not be reusable through the import or include statements.
• The the Salami Slice approach http://blogs.msdn.com/skaufman/archive/2005/04/25/411809.aspx
All elements are defined globally but the type definitions are defined locally. This way other schemas may reuse the elements. With this approach, a global element with its locally defined type provide a complete description of the elements content. This information 'slice' is declared individually and then aggregated back together and may also be pieced together to construct other schemas.
• The Venetian Blind approach http://blogs.msdn.com/skaufman/archive/2005/04/29/413491.aspx
Similar to the Russian Doll approach in that they both use a single global element. The Venetian Blind approach describes a modular approach by naming and defining all type definitions globally (as opposed to the Salami Slice approach which declares elements globally and types locally). Each globally defined type describes an individual "slat" and can be reused by other components. In addition, all the locally declared elements can be namespace qualified or namespace unqualified (the slats can be "opened" or "closed") depending on the elementFormDefault attribute setting at the top of the schema.

Resources