how to define xsd element with multiple option? - xsd

I have scenario where I have to use the same XSD element for different purpose so that my resulting XML can contain either one or more p tags but not all.
<p>some paragraph here </p>
<p>
<img src = "....." alt="......"/>
</p>
<p> <b> some text here <b> <p>
<p> ...... <g1> ........ <g2>.......<g3>........<p>
I am new to XML Schema, Thanks in advance.

The assumption I am making is that you're trying to define the p tag, by showing its different content models. The first thing is that by taking in text, you have to define its content as mixed. From there, you could use a repeating choice that lists all other elements, such as img, b, g1, g2, etc.
I am showing an excerpt from the XHTML XSD:
<xs:element name="p">
<xs:complexType mixed="true">
<xs:complexContent>
<xs:extension base="Inline">
<xs:attributeGroup ref="attrs" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:complexType name="Inline" mixed="true">
<xs:annotation>
<xs:documentation>
"Inline" covers inline or "text-level" elements
</xs:documentation>
</xs:annotation>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="inline" />
<xs:group ref="misc.inline" />
</xs:choice>
</xs:complexType>
etc.
A good learning might be to look at the XTHML XSD. You could use an XSD editor to investigate the structures associated with the p tag.

Related

XSD variable element names

Is it possible in XSD to name an element dynamically?
I have a complexType with a varying (but limited) number of elements (x-n), each of which has a complicated substructure. I can copy and paste one (x-1) and just change the number for the name of each of the copies (x-2, x3, and so on), but it'd be cleaner if I didn't have to.
For example, as it is now:
<xs:schema attributeFormDefault="unq1" elementFormDefault="q1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="r1">
<xs:complexType><xs:sequence>
<xs:element name="w-s">
<xs:complexType><xs:sequence maxOccurs="4">
<xs:element name="x-1" minOccurs="0">
<xs:complexType><xs:sequence>
<!-- long tedious substructure goes here -->
</xs:sequence></xs:complexType>
</xs:element>
<xs:element name="x-2" minOccurs="0">
<xs:complexType><xs:sequence>
<!-- long tedious substructure goes here -->
</xs:sequence></xs:complexType>
</xs:element>
<xs:element name="x-3" minOccurs="0">
<xs:complexType><xs:sequence>
<!-- long tedious substructure goes here -->
</xs:sequence></xs:complexType>
</xs:element>
<xs:element name="x-4" minOccurs="0">
<xs:complexType><xs:sequence>
<!-- long tedious substructure goes here -->
</xs:sequence></xs:complexType>
</xs:element>
</xs:sequence></xs:complexType>
</xs:element>
</xs:sequence></xs:complexType>
</xs:element>
</xs:schema>
Looking through w3schools now (https://www.w3schools.blog/xsd-xml-schema-definition-tutorial), the answer is not jumping out at me yet, and it's starting to look like the answer is "No.".
I can copy and paste one (x-1) and just change the number
If each element x-n has the same content then you should use the same tag name for all of these tags. That will require a change in the XML format, so I would also recommend that you stop using this style:
<element name='x-n' ...>
...and start using this instead:
<x index="n">
This will make your life much easier because XML schema expects the tag name to indicate the type of content.
I understand that you may not be able to change the XML format, but I think it's important to point out that your current style of XML is not best practice.
Judging by these stackoverflows, the answer appears to be "Not only no, but also you're wrong for asking" :-p
xml schema list of incremental element name
Can't design xsd schema - because of a variable element name
XML variable tag names
The better solution is to restructure the XSD so that the x-n element has a sub-element indicating the value of n, like so:
<xs:schema attributeFormDefault="unq1" elementFormDefault="q1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="r1">
<xs:complexType><xs:sequence>
<xs:element name="w-s">
<xs:complexType><xs:sequence maxOccurs="4">
<xs:element name="x" minOccurs="0">
<xs:complexType><xs:sequence>
<xs:element name="x-number">
<!-- long tedious substructure goes here -->
</xs:sequence></xs:complexType>
</xs:element>
</xs:sequence></xs:complexType>
</xs:element>
</xs:sequence></xs:complexType>
</xs:element>
</xs:schema>

distincting xs:choices in xsd by using fixed values for element with enumeration type

Is it possible to distinct xs:choices in xsd by using fixed values? I have a simple type:
<xs:simpleType name="datatypeCategory">
<xs:restriction base="xs:string">
<xs:enumeration value="SIMPLE"/>
<xs:enumeration value="COMPLEX"/>
<xs:enumeration value="COLLECTION"/>
</xs:restriction>
</xs:simpleType>
And what I want to achieve is
<xs:element name="datatype">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element id="category" type="datatypeCategory" fixed="SIMPLE"/>
<!-- some fields specific for SIMPLE -->
</xs:sequence>
<xs:sequence>
<xs:element id="category" type="datatypeCategory" fixed="COMPLEX"/>
<!-- some fields specific for COMPLEX -->
</xs:sequence>
<xs:sequence>
<xs:element id="category" type="datatypeCategory" fixed="COLLECTION"/>
<!-- some fields specific for COLLECTION -->
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
When I do this my XMLSpy tells me:
# The content model of complex type definition '{anonymous}' is ambiguous.
# Details: cos-nonambig: <xs:element name='category'> makes the content model non-deterministic against <xs:element name='category'>. Possible causes: name equality, overlapping occurrence or substitution groups.
You can't do exactly that. The error is because a simple validator that sees a <category> element won't immediately know which branch of the choice to take, and XML Schema 1.0 supports such simple validators.
An alternative would be to name each element according to the category.
<xs:element name="datatype">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="simpleCategory" type="empty"/>
<!-- some fields specific for SIMPLE -->
</xs:sequence>
<xs:sequence>
<xs:element name="complexCategory" type="empty"/>
<!-- some fields specific for COMPLEX -->
</xs:sequence>
<xs:sequence>
<xs:element name="collectionCategory" type="empty"/>
<!-- some fields specific for COLLECTION -->
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
where empty is defined as an empty type. Or give them complex types to hold the "specific fields". There are other alternatives depending on your constraints, such as using substitution groups or derived complex types.
In general though, XML Schema 1.0 is not good for constraints based on interrelated values. For that, you have to go to XML Schema 1.1 or an external tool.
IDs must be unique within a document. You can't use the same value on multiple elements:
http://www.w3.org/TR/2006/REC-xml11-20060816/#id

minOccurs/maxOccurs in XML Schema

Given this XML Schema snippet:
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="param" type="param" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="format" type="format" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" />
</xs:complexType>
</xs:element>
The intended result is valid <data> elements may contain 0 or more <param> elements followed by 0 or more <format> elements. Have I added the minOccurs/maxOccurs atttributes correctly, or should they be applied to the containing <xs:sequence>?
Correct or not, what would be the result of going one way or the other?
You have done it right and you can not add min/max occurs to sequence element. Using and XML editor that supports XML Schema might help you to validate your assumptions when you are in doubt. Here is a good free ware called XMLFox

XSD and plain text

I have a rest/xml service that gives me the following...
<verse-unit unit-id="38009001">
<marker class="begin-verse" mid="v38009001"/>
<begin-chapter num="9"/><heading>Judgment on Israel&apos;s Enemies</heading>
<begin-block-indent/>
<begin-paragraph class="line-group"/>
<begin-line/><verse-num begin-chapter="9">1</verse-num>The burden of the word of the <span class="divine-name">Lord</span> is against the land of Hadrach<end-line class="br"/>
<begin-line class="indent"/>and Damascus is its resting place.<end-line class="br"/>
<begin-line/>For the <span class="divine-name">Lord</span> has an eye on mankind<end-line class="br"/>
<begin-line class="indent"/>and on all the tribes of Israel,<footnote id="f1">
A slight emendation yields <i>
For to the <span class="divine-name">Lord</span> belongs the capital of Syria and all the tribes of Israel
</i>
</footnote><end-line class="br"/>
</verse-unit>
I used visual studio to generate a schema from this and used XSD.EXE to generate classes that I can use to deserialize this mess into programmable stuff.
I got everything to work and it is deserialized perfectly (almost).
The problem I have is with the random text mixed throughout the child nodes. The generated verse-unit objects gives me a list of objects (begin-line, begin-block-indent, etc), and also another list of string objects that represent the bits of string throughout the xml.
Here is my schema
<xs:element maxOccurs="unbounded" name="verse-unit">
<xs:complexType mixed="true">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="marker">
<xs:complexType>
<xs:attribute name="class" type="xs:string" use="required" />
<xs:attribute name="mid" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="begin-chapter">
<xs:complexType>
<xs:attribute name="num" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="heading">
<xs:complexType mixed="true">
<xs:sequence minOccurs="0">
<xs:element name="span">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="class" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="begin-block-indent" />
<xs:element name="begin-paragraph">
<xs:complexType>
<xs:attribute name="class" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="begin-line">
<xs:complexType>
<xs:attribute name="class" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="verse-num">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:unsignedByte">
<xs:attribute name="begin-chapter" type="xs:unsignedByte" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="end-line">
<xs:complexType>
<xs:attribute name="class" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="end-paragraph" />
<xs:element name="end-block-indent" />
<xs:element name="end-chapter" />
</xs:choice>
</xs:sequence>
<xs:attribute name="unit-id" type="xs:unsignedInt" use="required" />
</xs:complexType>
</xs:element>
WHAT I NEED IS THIS. I need the random text that is NOT surrounded by an xml node to be represented by an object so I know the order that everything is in.
I know this is complicated, so let me try to simplify it.
<field name="test_field_0">
Some text I'm sure you don't want.
<subfield>Some text.</subfield>
More text you don't want.
</field>
I need the xsd to generate a field object with items that can have either a text object, or a subfield object. I need to no where the random text is within the child nodes.
You can try Xml Schema Mixed Content, which is well explained here: http://www.w3schools.com/schema/schema_complex_mixed.asp
I don't know much about the .net side. But this somewhat older article says that mixed mode is basically supported by xsd.exe: http://msdn.microsoft.com/en-us/magazine/cc164135.aspx
Well your problem starts here:
<xs:element name="begin-line">
<xs:complexType>
<xs:attribute name="class" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
What this means is that a "begin line" type has an attribute called class (Which means the tag can have an attribute class like so: <begin-line class="lineclass">. However it is simply a type xs:string which means that all you get is a string.
I also don't know if this is an option, but if your XML could be made to have closing tags like this line for instance:
<begin-line class="indent"/>and Damascus is its resting place.<end-line class="br"/>
XML should be like this:
<begin-line class="indent"/>and Damascus is its resting place.</begin-line class="br">
I believe that if all the "line" tags were closed properly then the XSD generator might have a better time trying to derive what is inside the "begin-line" XML tag. Indeed if this is possible then you could rename begin-line to line and begin-chapter to chapter which should make your XML much more readable.
If it's not possible to update your code, then you are going to have to try your best with the string itself. I'm not sure if verses contain pure HTML, but if so you could parse the string inside the begin-line element as XML itself, using the library to jump between values and nodes (you might have to wrap a pair of tags around the string before trying to parse it though).

xsd: How to extend a type with an unordered list of elements

This is a part of my xml schema
<xs:complexType name="Friend">
<xs:all>
<xs:element name="name" type="xs:string" />
<xs:element name="phone" type="xs:string" />
<xs:element name="address" type="xs:string" />
</xs:all>
</xs:complexType>
<xs:complexType name="Coworker">
<xs:all>
<xs:element name="name" type="xs:string" />
<xs:element name="phone" type="xs:string" />
<xs:element name="office" type="xs:string" />
</xs:all>
</xs:complexType>
For better maintainability, I would like to have the shared attributes in an (abstract) super type or something like that. But more important, I want that all elements are unordered and also optional.
Is this possible, and what is the best way to do it?
You have to limit yourself a little bit, some of the things you are trying to do are not possible in XML Schema.
Suppose you introduce a complex type called Person to be a super-type of Friend and Coworker. Here are your options:
Replace xs:all with xs:sequence, remove name and phone from the sub-types, add to the super-type, and add inheritance. Your elements now have to be ordered, but you can make them individually optional. It is illegal to use xs:all in type hierarchies in XML Schema, because the processor cannot tell where the parent content model stops and the child content model starts.
Replace xs:all with <xs:choice maxOccurs="unbounded"> in both types, and add your inheritance. Then your elements become unordered again, but they may repeat.
So in conclusion: given your type names up there, I would guess that your requirements will not be exactly met. I would go for the first option: insisting on arbitrary element order is often not as useful as it seems.
One-and-half year after this question and the accepted answer were posted, XSD 1.1 was published. In this version it is possible to specify what the OP asked for because a number of restriction on xs:all were lifted. One of them is that it is now possible to extend an xs:all.
Using XSD 1.1 you can specify the following:
<xs:complexType name="Person" abstract="true">
<xs:all>
<xs:element name="name" type="xs:string" minOccurs="0" />
<xs:element name="phone" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
<xs:complexType name="Friend">
<xs:complexContent>
<xs:extension base="Person">
<xs:all>
<xs:element name="address" type="xs:string" minOccurs="0" />
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Coworker">
<xs:complexContent>
<xs:extension base="Person">
<xs:all>
<xs:element name="office" type="xs:string" minOccurs="0" />
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
This defines the following types:
Person: an abstract type with optional unordered name and phone elements;
Friend: extends Person adding an optional address element to the list of unordered elements;
Coworker: extends Coworker adding an optional office element to the list of unordered elements.
Note that this solution does not work for every XML processor: even though 8 years have passed since the publication of XSD 1.1, a lot of processors still only support XSD 1.0.

Resources