How to define a Constant in XSD - 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?

Related

Set attribute to all types in XML Schema

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.

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.

Is this the proper way to added enumerated attributes to a complexType?

Is this the proper way to set an attribute with enumerated values on the complexType AvailStatusMessageType. I see a lot of examples that declare a complexContent section right below the complexType declaration? What is this complexContent for and is it necessary here?
<xs:complexType name="AvailStatusMessageType">
<xs:sequence>
<xs:element name="LengthsOfStay" type="LengthsOfStayType" />
<xs:element name="RestrictionStatus" type="RestrictionStatusType"/>
</xs:sequence>
<xs:attribute name="BookingLimit">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SetLimit" />
<xs:enumeration value="AdjustLimit"/>
<xs:enumeration value="RemoveLimit"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
Element types can be divided into two categories in XML Schemas
Elements that can contain structural markup (attributes or child elements)
Elements that contain only textual markup
Further, the elements that contain markup (group 1) can be again divided to two groups
Elements that are allowed to have child elements
Elements that are not allowed to have child elements
First division separates (1) <complexType> and (2) <simpleType>. Second one separates (1) <complexContent> and (2) <simpleContent>.
<xs:complexContent> is not usually seen, because it is an implicit default so the whole structure can be abbreviated by omitting that element. This common structure
<xs:complexType>
... (<xs:sequence> or anything) ...
</xs:complexType>
is actually identical to
<xs:complexType>
<xs:complexContent>
<xs:restriction base="xs:anyType">
... (<xs:sequence> or anything) ...
</xs:restriction>
</xs:complexContent>
</xs:complexType>
In your structure an element with type "AvailStatusMessageType" 1) contains markup 2) and has child elements. So your structure is a complex type with complex content. Your example seems correct even though you haven't used the <xs:complexContent> element, because you are actually using the abbreviated form. It is identical to this:
<xs:complexType name="AvailStatusMessageType">
<xs:complexContent>
<xs:restriction base="xs:anyType">
<xs:sequence>
<xs:element name="LengthsOfStay" type="LengthsOfStayType" />
<xs:element name="RestrictionStatus" type="RestrictionStatusType"/>
</xs:sequence>
<xs:attribute name="BookingLimit">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SetLimit" />
<xs:enumeration value="AdjustLimit"/>
<xs:enumeration value="RemoveLimit"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
A complex type may have simple or complex content. You would use <simpleContent> if you were defining a complex type with simple content. You must use the <complexContent> element when you are restricting or extending another complex type (because you specify the base type as an attribute in the <complexContent> element). If you are simply creating a complex type (with complex content), as you are doing, you may use (but are not required to use) the <complexContent> element.
Your enumeration looks right.

How to define an appropriate complex type?

I have this in my xsd:
<xs:element name="Parameter" type="complex">
and I want to define complex like:
<xs:simpleType name="complex">
1 xs:decimal
2 xs:string
</xs:simpleType>
So if the value for Parameter is decimal to take decimal and if value is not decimal to assume that value is string. How to declare my complex type?
You'll need a complexType together with a choice to express this:
<xs:complexType name="complex">
<xs:choice>
<xs:element name="number" type="xs:decimal"/>
<xs:element name="string" type="xs:string"/>
</xs:choice>
</xs:complexType>
Edit: Based on your comments maybe this is worth a try:
<xs:simpleType name="monat">
<xs:union memberTypes="xs:decimal xs:string"/>
</xs:simpleType>
But JAXB will translate this to String anyway, so there's no benefit from the union, at least with respect to the generated classes. And that you are using JAXB is just a guess.

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.

Resources