RE: Expressing relations between types

Michael Kay, le 30 novembre 2007 19:22:
>> I am thus wondering if there is a better way to define "related"
>> types like this. For example, is there a way to express the
>> definition of EntryPredicate by saying something like "this is the
>> same thing than an Entry, replacing dateTime by dateTimeRange,
>> unsingedInt by unsignedIntRange"?
> 
> Not within the XML Schema language.
> 
> Sometimes when your application contains higher-level structures or
> patterns like this, it can be appropriate to describe the high-level
> structure in your own notation and then generate the XML Schema
> definitions from this
> (typically using XSLT to do the transformation).

Thanks for replying.

I had the following (crazy?) idea, and would be grateful for any comments about it:

First enumerate the names of the elements, grouping them by their associated types:
  <xs:simpleType name="StringElementName">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Subject"/>
      <!-- Name of other elements of type "string" go here... -->
    </xs:restriction>
  </xs::simpleType>
  
  <xs:simpleType name="DateTimeElementName">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Received"/>
      <!-- Name of other elements of type "dateTime" go here... -->
    </xs:restriction>
  </xs::simpleType>
  
  <xs:simpleType name="BooleanElementName">
    <xs:restriction base="xs:string">
      <xs:enumeration value="IsViewed"/>
      <!-- Name of other elements of type "boolean" go here... -->  
  </xs::simpleType>
  
  <xs:simpleType name="UnsignedIntElementName">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Pages"/>
      <!-- Name of other elements of type "unsignedInt" go here... -->  
  </xs::simpleType>

Then define Entry as simply being a bunch of EntryElements:
  <xs:complexType name="Entry">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Element" type="EntryElement" />
    </xs:sequence>
  </xs:complexType>

An EntryElement being a named string, dateTime, boolean or unsignedInt:
  <xs:complexType name="EntryElement">
    <xs:choice>
      <xs:element name="String"/ type="StringEntryElement"/>
      <xs:element name="DateTime"type="DateTimeEntryElement"/>
      <xs:element name="Boolean" type="BooleanEntryElement"/>
      <xs:element name="UnsignedInt" type="UnsignedIntEntryElement"/>
    </xs:choice>
  </xs:complexType>
  
  <xs:complexType name="StringEntryElement">
    <xs:sequence>
      <xs:element name="Name" type="StringElementName"/>
      <xs:element name="Value" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="DateTimeEntryElement">
    <xs:sequence>
      <xs:element name="Name" type="DateTimeElementName"/>
      <xs:element name="Value" type="xs:dateTime"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="BooleanEntryElement">
    <xs:sequence>
      <xs:element name="Name" type="BooleanElementName"/>
      <xs:element name="Value" type="xs:boolean"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="UnsignedIntEntryElement">
    <xs:sequence>
      <xs:element name="Name" type="UnsignedIntElementName"/>
      <xs:element name="Value" type="xs:unsignedInt"/>
    </xs:sequence>
  </xs:complexType>

Now, I can reuse the "xxxElementName" defined above in the definition of EntryPredicate:
  <xs:complexType name="EntryPredicate">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="Predicate" type="PredicateElement" />
    </xs:sequence>
  </xs:complexType>
  
  <xs:complexType name="PredicateElement">
    <xs:choice>
      <xs:element name="String"/ type="StringPredicateElement"/>
      <xs:element name="DateTime"type="DateTimePredicateElement"/>
      <xs:element name="Boolean" type="BooleanPredicateElement"/>
      <xs:element name="UnsignedInt" type="UnsignedIntPredicateElement"/>
    </xs:choice>
  </xs:complexType>
  
  <xs:complexType name="StringPredicateElement">
    <xs:sequence>
      <xs:element name="Name" type="StringElementName"/>
      <xs:element name="Value" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="DateTimePredicateElement">
    <xs:sequence>
      <xs:element name="Name" type="DateTimeElementName"/>
      <xs:element name="Begin" type="xs:dateTime"/>
      <xs:element name="End" type="xs:dateTime"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="BooleanPredicateElement">
    <xs:sequence>
      <xs:element name="Name" type="BooleanElementName"/>
      <xs:element name="Value" type="xs:boolean"/>
    </xs:sequence>
  </xs:complexType>    
  <xs:complexType name="UnsignedIntPredicateElement">
    <xs:sequence>
      <xs:element name="Name" type="UnsignedIntElementName"/>
      <xs:element name="Begin" type="xs:unsignedInt"/>
      <xs:element name="End" type="xs:unsignedInt"/>
    </xs:sequence>
  </xs:complexType>

If I want to add another parameter to my web method to allow the caller to specify an ordering for the returned elements, I could define it like this:
  <xs:complexType name="SortingElement">
    <xs:sequence>
        <xs:choice>
            <xs:element name="ElementName" type="StringElementName"/>
            <xs:element name="ElementName" type="DateTimeElementName"/>
            <xs:element name="ElementName" type="BooleanElementName"/>
            <xs:element name="ElementName" type="UnsignedIntElementName"/>
        </xs:choice>
        <xs:element name="Ascending" type="xs:boolean"/>
    </xs:sequence>
  </xs:complexType>

If you read up to here:
1) Congratulations
2) Do you have any comments?


Éric Malenfant
---------------------------------------------

Received on Tuesday, 4 December 2007 20:41:03 UTC