Groups | Blog | Home
all groups > dotnet xml > february 2004 >

dotnet xml : Interesting Problem with Child element order


(jrmsmo NO[at]SPAM hotmail.com)
2/25/2004 7:48:34 AM
Hi there, I have an interesting problem that maybe you pros can suggest how I solve.
I'm working with a third party program that serializes an XML document (it was obviously not designed with schema in mind). I created a schema from this document. It works fine. Except for some unknown reason, in a small part of the XML document, this program switches the order around, and of course the validator I built then fails.
Its always the same two elements it switches (from top to bottom and bottom to top)
ex:
Some documents have the metaID on top, some on the bottom, these are the only two elements that ever get switched.
I need my validator program to handle both of the below document types and not throw errors.

Some documents are:

<Metadata>
<MetaID>{65C97878-11D5-4599-B5AD-7C5BFB9B591D}</MetaID>
<CreaDate>20040223</CreaDate>
<CreaTime>08552300</CreaTime>
<SyncOnce>FALSE</SyncOnce>
<SyncDate>20040225</SyncDate>
<SyncTime>10445400</SyncTime>
<ModDate>20040225</ModDate>
<ModTime>10445400</ModTime>
</Metadata>

Some are:


<Metadata>
<CreaDate>20040225</CreaDate>
<CreaTime>09500700</CreaTime>
<SyncOnce>FALSE</SyncOnce>
<SyncDate>20040225</SyncDate>
<SyncTime>10445100</SyncTime>
<ModDate>20040225</ModDate>
<ModTime>10445100</ModTime>
<MetaID>{469F6DEE-4EFF-48E6-9D66-39C0D6776DF2}</MetaID>
</Metadata>


Of course schema by its nature defines the order of child elements. Is there anyway I can force the MetaID element to be ignored? Or should I approach this by adding code to my project to ensure this element is placed first? (as defined in myschema)
I don't know how I should approach this problem.
thanks a bunch!

**********************************************************************
Sent via Fuzzy Software @ http://www.fuzzysoftware.com/
Derek Harmon
2/25/2004 9:22:12 PM
[quoted text, click to view]

The first idea that might come to mind is to make the MetaID at the top optional
(minOccurs=0, maxOccurs=1) and the MetaID at the bottom optional. This fails
to detect when there is no MetaID (I am assuming MetaID is required, but may
be either the first or last child element), so we dismiss it.

In this scenario, there's really no other way but to declare the sequence twice.
One sequence compositor defines elements in the order: MetaID, CreaDate,
...., ModTime. A second sequence compositor defines elements in the order:
CreaData, ..., ModTime, MetaID. These two compositors are then placed
under a choice compositor, meaning either one sequence or the other is
valid for each instance of the MetaData element.

- - - MetaData1.xsd (excerpt)
<!-- Type definition. -->
<xsd:complexType name="MetaDataType">
<!-- Sequence A _or_ B is valid. -->
<xsd:choice>
<!-- Definition of Sequence A. -->
<xsd:sequence>
<xsd:element name="MetaID" type="xsd:string" />
<xsd:element name="CreaDate" type="xsd:string" />
<!-- . . . -->
<xsd:element name="ModTime" type="xsd:string" />
</xsd:sequence>
<!-- Definition of Sequence B. -->
<xsd:sequence>
<xsd:element name="CreaDate" type="xsd:string" />
<!-- . . . -->
<xsd:element name="ModTime" type="xsd:string" />
<xsd:element name="MetaID" type="xsd:string" />
</xsd:sequence>
</xsd:choice>
</xsd:complexType>

<!-- Element declaraction (may be local). -->
<xsd:element name="MetaData" type="MetaDataType" />

- - -

Admittedly, the redundancy in the sequence is something we want to
avoid. The presence of such repetition in a schema is an opportunity
for error because it creates two sequences that demand synchronized
maintenance when revising the schema. What can be done?

Fortunately XML Schema furnishes the group construct for composing
a global model that can be referenced from within type definitions. Think
of a group as short-hand for the model that it defines, an alias-of-sorts.

Here's how the schema looks,

- - - MetaData2.xsd (excerpt)
<!-- Define the group globally. -->
<xsd:group name="MetaDataCoreGroup" >
<xsd:sequence>
<xsd:element name="CreaDate" type="xsd:string" />
<xsd:element name="CreaTime" type="xsd:string" />
<xsd:element name="SyncOnce" type="xsd:string" />
<xsd:element name="SyncTime" type="xsd:string" />
<xsd:element name="ModDate" type="xsd:string" />
<xsd:element name="ModTime" type="xsd:string" />
</xsd:sequence>
</xsd:group>

<!-- Define the MetaData type as above, but referencing the group. -->
<xsd:complexType name="MetaDataType">
<xsd:choice>
<xsd:sequence>
<xsd:element name="MetaID" type="xsd:string" />
<xsd:group ref="MetaDataCoreGroup" />
</xsd:sequence>
<xsd:sequence>
<xsd:group ref="MetaDataCoreGroup" />
<xsd:element name="MetaID" type="xsd:string" />
</xsd:sequence>
</xsd:choice>
</xsd:complexType>

<xsd:element name="MetaData" type="MetaDataType" />

- - -

As you can see, this strongly types the MetaID whether it appears at
the top or bottom of the children of the MetaData element. This turns
out to be better than ignoring the element (in which case the schema
would give up on trying to identify what element is there, and potentially
incorrect instance documents may be regarded as schema-valid); and
its something that XML Schema supports without duplication of the
content model, which is vital in large schema that must be maintained.


Derek Harmon

AddThis Social Bookmark Button