views:

204

answers:

1

I'm having trouble creating an XSD for some xml.

A bit of background might help. The xml is for messaging. In particular, the message is designed to be simple, and designed to be cross referenced easily. At its heart is a recursive key value set up.

Simple Key values are like this.

    <key name="quantity">5</key>
    <key name="price" representation="percentage">99.78</key>

There is an optional representation attribute where the infromation could be represented in two different forms.

Reference Key Values are like this

    <key name="currency" reference="instrument">
        <id name=" INSID" system="XXXX" instance="PROD">DEM</id>
        <id name=" EXTERN_ID1" system="XXXX" instance="PROD"> ext128k</id>
    </key>

This form is used for foreign key references or for references to enumerations. The cross reference service will select out all keys with an attribute of reference. It will then get all possible ids for that reference, and add in additional id fields, and replace that sub element with the new version.

ie "./key[@reference]" as an Xpath can get all the enumerations and references from the xml

Lastly there is a the recursive structure. Here the value part of the key value, can be a key value itself.

<key name="trade" type="trade">
    <key name="value_day">1999-03-12</key>
    <key name="quantity">5</key>
    <key name="leg" type="leg">
        <key name="rate">5.00</key>
        <key name="period">3m</key>
        <key name="cashflows" type="cashflows">
            <key name="cashflow">10</key>
            <key name="cashflow">20</key>
        </key>
    </key>
</key>

Now, I'm having real trouble creating an XSD for this structure.

Can anyone help?

Thanks

Nick

A: 

If I understand correctly, you wish that you could write Schema like this:

<!-- WARNING: this is not valid Schema -->
<xs:complexType name="composite-key">
  <xs:choice maxOccurs="unbounded">
    <xs:element name="key" type="simple-key"/>
    <xs:element name="key" type="composite-key"/>
  </xs:choice>
  <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

simple-key would be defined elsewhere. This is not valid Schema since you are not allowed to use the same element name twice. If Schema supported this, it would have a devil of a time disambiguating element types based upon their structure alone.

If you have control over the XML, you can make this work by changing one or both of the element names. For example, one might use val for simple values and obj for composite ones:

<xs:complexType name="composite-key">
  <xs:choice maxOccurs="unbounded">
    <xs:element name="val" type="simple-key"/>
    <xs:element name="obj" type="composite-key"/>
  </xs:choice>
  <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

Adjust the names to taste. This would be my recommended solution as it emphasizes clarity. However, the element names may be out of your control. If so, a less satisfactory solution would be as follows:

<xs:complexType name="key" mixed="true">
  <xs:sequence maxOccurs="unbounded">
    <xs:element name="key" type="key"/>
  </xs:sequence>
  <xs:attribute name="name" type="xs:string" use="required"/>
  <xs:attribute name="type" type="xs:string"/>
  <xs:attribute name="representation" type="xs:string"/>
</xs:complexType>

The key differences here are the mixed content type, and the unfortunate fact that the declaration is now an amalgam of the simple and composite key types. I say that this is "less satisfactory" because now you must perform additional validity checking in your own code, after Schema has finished with it. For example, you would need to validate whether the set of attributes given make sense for the implied key type. Also, the example as written would permit text to appear anywhere between nested key elements -- probably something you do not want.

[edit: the same question is discussed on stackoverflow here]

WReach