Yow-Hann Lee - Software Happens

All things Computer Science, .NET & WWW

  Home  |   Contact  |   Syndication    |   Login
  127 Posts | 7 Stories | 27 Comments | 50 Trackbacks

News


Article Categories

Archives

Post Categories

About

Have you ever been frustrated by some of the brittleness in XSD schemas? Granted, this may sound like an oxymoron since XSDs were enforced in the first place to provide strict xml structure.

But let's think about XML based technologies for a moment...

The claim to fame for XML was the flexibility of having variable number of attributes, etc for your business objects. And with your XML, you could perform XPath queries to your heart's content. What was great about XPath was that it is was order independent (unless of course you explicitly called for one return node, SelectNode, in the BCL API and the xml blob consisted of multiple nodes that could be returned with the expression, SelectNodes).

So where did XSD fit in?

Well, in the wild wild west of XML, you could think of it as the cheriff in town.

Unfortunately, there are just some things in XSD that are a little too strict. Thus, making life difficult on the developer.

SCENARIO:

Let's take for instance you want your XSD to govern the following structure:

<Drink name="mikes">

<AlcoholPercentage>5</AlcoholPercentage>

</Drink>

<Food name="calzone" calories="700">

-- Some other elements in here --

</Food>

<Food name="chicken" calories="350">

-- Some other elements in here --

</Food>

 

So the rule is that you can only have 1 Drink node but can have multiple Food nodes. It must be flexible enough to be order independent.

<Food name="calzone" calories="700">

-- Some other elements in here --

</Food>

<Food name="chicken" calories="350">

-- Some other elements in here --

</Food>

<Drink name="mikes">

<AlcoholPercentage>5</AlcoholPercentage>

</Drink>

RULES:

But the rules are as follows:

  • Drink must occur once
  • Food can occur a minOccurs="0" and maxOccurs="unbounded"
  • The two are order independent as shown above

However, because you are performing XPath queries on this data, you do not care what order they come in. The xml structure should be flexible enough so that a developer on another project playing with your data can simply RemoveChild and AppendChild on any nodes without affecting the expected behavior.

So right away, if you were thinking of specifying "<xs:sequence>..." with your complexType and element names underneath, it is ruled out.

Then, perhaps an idea pops up in using an "<xs:any.." tag at the end of the sequence. But that also gets ruled out right away because it will introduce the violation of drink occuring only once.

So then the idea for using a "<xs:choice>" seems appropriate. For the purposes of this simplified version, that would seem like the likely answer. All you have to do is specify two sequences under choice and pick one or the other right?

Well, not exactly. As I mentioned, this example is an oversimplification of the actual scenario. Thus, in the real world, with your complexTypes nested under one another, you would end up with something along the lines of:

So now you're thinking, the xml structure is flawed. You want to do anything ranging from revamping the entire xml blob to minor changes. (i.e. If you really wanted this, why not place Food under a Foods parent node? But let's go back to the original requirement. It must follow this exact xml structure. Sometimes, you don't have the luxury to decide on this.)

And hence the rant on XSD flexibility! Well, perhaps there is some way of circumventing all of the hassles here and still satisfying the requirements. But for simple requirements such as this, the xsd definition should not be so verbose. Also, wasn't the XML vision to have all its technologies play nicely together: xpath, xml, xslt, xsd? XPath is order independent and therefore, there should be a quick and easy way to do it. (yes, there's choice and any, but those don't work as well - see above).

If you do have a simple solution, please do share. =)

posted on Sunday, March 25, 2007 11:24 AM

Feedback

# re: A Rant on XSD Schemas 3/26/2007 8:51 AM John Workman
This may not be the best solution, but I think it will work. I do get the following warning, but I think it will still work.

Multiple definition of element 'Food' causes the content model to become ambiguous. A content model must be formed such that during validation of an element information item sequence, the particle contained directly, indirectly or implicitly therein with which to attempt to validate each item in the sequence in turn can be uniquely determined without examining the content or attributes of that item, and without any information about the items in the remainder of the sequence.

What I did was define food as 0 to many, then defined drink as 0 to 1, then repeated food as 0 to many. This allows the drink to be first, last, or in the middle.

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="NewDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Food" type="food" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Drink" type="drink" minOccurs="0" maxOccurs="1"/>
<xs:element name="Food" type="food" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="food">
<xs:sequence>
<xs:element name="calories"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="drink">
<xs:sequence>
<xs:element name="AlcoholPercentage"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>


# re: A Rant on XSD Schemas 3/26/2007 8:52 AM John Workman
btw, in my test file I changed the calories from an attribute to an element, you will need to change it back before testing it.

# Link Listing - March 26, 2007 3/26/2007 11:25 PM Christopher Steen
telerik radEditor for Office SharePoint Server 2007 has been officially released! + Telerik for MCMS...

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: 
Please add 5 and 2 and type the answer here: