Re: Extensibility Question

Hi Michael,

>I should have provided more context for my question, though. So to elaborate, the parameter structure I described earlier will be contained in an Operation element that has Type and Name attributes:
>
><Operation Type="" Name="">
>   <Parameters>
>      <Parameter Name="" Type="" Direction="">
>         <Value></Value>
>      </Paramater>
>   </Parameters>
></Operation>
>
>We'll send these requests to different handlers based on the type of
>operation (a couple of internal types and an external interface type). So
>if the request is for one of our internal processes the handler will expect
>to extract the parameters as shown. However if the operation type is an
>external interface, then its Name will also be used to route the request to
>a dedicated handler for that interface. This implies a completely different
>functional thread than the simpler processes we would perform internally,
>so it's very likely that the external interface would require it's own
>complete schema. So instead of "Parameters", at this point I should drop in
>whatever data is appropriate to the specified interface. This data would be
>passed on to the appropriate handler, which would know how to deal with it.
>
 From what I can understand this means that you have no control over the 
structure of these external interfaces. I think your best bet then is to 
go with your original proposal and use the <xs:any> element and stick to 
a simple content model like:

<xs:choice>
  <xs:element name="Parameters"/>
  <xs:any namespace="##other"/>
</xs:choice>

Depending on if you want the extrnal interfaces to be validated or not 
you can set the processContents attribute on the xs:any element to 
"lax", "strict" or "skip". Based on the information you provided though 
my guess is that you definately want this external information to be 
validated so you should probably set this value to "strict".
This means that the W3C XML Schema processor you're using _must_ have 
the schema for this external interface available. Depending on your 
application you can provide this through the API or you can specify this 
using the xsi:schemaLocation attribute on the external interface in your 
instance document. Example:

Base schema:
--------------
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="Operation">
    <xs:complexType>
      <xs:choice>
        <xs:element name="Parameters">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Parameter" type="myParameterType"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:any namespace="##other" processContents="strict"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
 
  <xs:complexType name="myParameterType">
    <xs:sequence>
      <xs:element name="value" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="datatype" type="xs:string" use="required"/>
    <xs:attribute name="direction" type="xs:string" use="required"/>
  </xs:complexType>
</xs:schema>

Instance:
---------
<?xml version="1.0" encoding="UTF-8"?>
<Operation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="Parameter_base.xsd">
  <Parameters>
    <Parameter datatype="" direction="">
      <value/>
    </Parameter>
  </Parameters>
</Operation>

An external interface schema can now look something like this:

External:
---------
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified" attributeFormDefault="unqualified" 
targetNamespace="www.external.com" xmlns:ext="www.external.com">
  <xs:complexType name="externalParameterType">
    <xs:sequence>
      <xs:element name="value" type="xs:string"/>
      <xs:element name="external" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="externalAtt" type="xs:string" use="required"/>
  </xs:complexType>
  <xs:element name="externalParameter" type="ext:externalParameterType"/>
</xs:schema>

and your instance can now instead be:

<?xml version="1.0" encoding="UTF-8"?>
<Operation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="Parameter_base.xsd" 
xmlns:ext="www.external.com">
  <ext:externalParameter xsi:schemaLocation="www.external.com 
externalInterface.xsd" externalAtt="">
    <ext:value/>
    <ext:external/>
  </ext:externalParameter>
</Operation>

In this instance we have specified the xsi:schemaLocation attribute for 
the top element of the external interface and since we have set 
validation to "strict" on the <xs:any> element this external information 
must be valid.
This design is completely open and an external interface can provide 
whatever data it wants as long as a schema can be provided to the 
validator. For more control you can specify the schema location in the 
API instead of in the XML instance document.
For some reason XML Spy 4.4 can't validate the above example but is 
works fine in Xerces 2.0.1 and MSXML 4.0.

Cheers,
/Eddie


>I suppose this is analogous to a SOAP body containing a custom encoding.
>(Duh, maybe I should go look at how the SOAP spec addresses this right? :-)
>I may in fact end up using SOAP to envelope this, but I'd still have to
>provide most of what we're developing.
>
>Michael A. Rossi
>Computer Sciences Corporation
>mailto:mrossi@csc.com
>856-983-4400 x4964
>
>
>                                                                                                                       
>                    Eddie Robertsson                                                                                   
>                    <erobertsson@allet                                                                                 
>                    te.com.au>                                                                                         
>                                                                                                                       
>                    08/06/2002 09:54                                                                                   
>                    PM                                                                                                 
>                                                                                                                       
>                                                                                                                       
>
>
>Hi Michael,
>
>  
>
>>I'm a relative newbie to XSDL (but an experienced markup developer),
>>so kindly excuse my ignorance if it should rear it's ugly head. I'm
>>developing a system interface schema and we'd like to leverage XSDL's
>>potential for datatype validation. For "internal" processes we have a
>>generic structure containing parameters, where each parameter has
>>attributes for name, type and direction (essentially name/value pairs).
>>Like so:
>>
>><parameter name="input1" datatype="Int" direction="In">
>>    <value>1</value>
>></parameter>
>><parameter name="output1" datatype="Int" direction="Out">
>>    <value>2</value>
>></parameter>
>>
>>This is fine for our puposes, but when we add external interfaces into
>>    
>>
>the
>  
>
>>mix we'll need to support more complex data exchange requirements. Most
>>likely, each interface will use its own schema, which can't be shoe-horned
>>in to our parameter structure (mostly because they'll want to validate
>>their datatypes at the parser level). While this is unavoidable, I'd
>>    
>>
>prefer
>  
>
>>that every interface used the rest of our mesasge framework so that we can
>>standardize on ways to handle things like authentication information. So
>>I'm considering doing something in my schema like (pseudo-spec):
>>
>><choice>
>>  <!element name="parameters"/>
>>  <any namespace=""##other"/>
>></choice>
>>
>>Any thoughts on whether this would be good, bad, done better some other
>>    
>>
>way
>  
>
>>would be most appreciated. TIA.
>>
>>    
>>
>I guess this depends on how much control you want to have over the
>external interfaces that can be added. If you use <xs:any> you don't
>really have any control at all and the external interfaces can pretty
>much add whatever they want.
>For more control I think this is a good use-case for substitutionGroups
>which allows one element to serve as a model in your schema and then the
>external interfaces could define their own "parameter" elements that can
>be used instead of the model. The base schema would contain the
>complexType that serves as the base type for the parameter-model element
>as well as the structure of your main schema. To illustrate I will use
>the following example:
>
>Base schema:
>--------------
><?xml version="1.0" encoding="UTF-8"?>
><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>elementFormDefault="qualified" attributeFormDefault="unqualified">
>  <xs:element name="Root">
>    <xs:complexType>
>        <!-- This is the content model that defines the parameter
>elements. Instead of having a choice between "parameter" and "any" this is
>now zero-or-more parameterModel elements. -->
>      <xs:sequence>
>        <xs:element ref="parameterModel" minOccurs="0"
>maxOccurs="unbounded"/>
>      </xs:sequence>
>    </xs:complexType>
>  </xs:element>
>
>  <!-- The "parameterModel" element is declared as abstract which means
>that it cannot by itself appear in an instance document. Instead one of
>the elements that are defined in the substitutionGroup for
>"parameterModel" must appear in the instance document. -->
>  <xs:element name="parameterModel" type="parameterBase" abstract="true"/>
>
>  <!-- Define the base type for the elements that can substitute the
>parameterModel element so that they at least must contain a "name"
>attribute. -->
>  <xs:complexType name="parameterBase">
>    <xs:attribute name="name" use="required" type="xs:string"/>
>  </xs:complexType>
>
>  <!-- Define the type for the local parameter element. This type must be
>derived from the "parameterBase" type so that any element of this type can
>be used instead of the "parameterModel" element. -->
>  <xs:complexType name="myParameterType">
>    <xs:complexContent>
>      <xs:extension base="parameterBase">
>        <xs:sequence>
>          <xs:element name="value" type="xs:string"/>
>        </xs:sequence>
>        <xs:attribute name="datatype" type="xs:string" use="required"/>
>        <xs:attribute name="direction" type="xs:string" use="required"/>
>    </xs:extension>
>    </xs:complexContent>
>  </xs:complexType>
>
>  <!-- Finally we define the local parameter element that can appear
>instead of the "parameterModel" in the instance document. This element is
>defined to be in the substitutionGroup of the "parameterModel" element.-->
>  <xs:element name="myParameter" type="myParameterType"
>substitutionGroup="parameterModel"/>
></xs:schema>
>
>Now, if only the above schema was used then an instance document could
>look like this (Note that the "myParameter" element is used instead of
>the "parameterModel" element.):
>
><?xml version="1.0" encoding="UTF-8"?>
><Root>
>  <myParameter name="input1" datatype="Int" direction="In">
>    <value>1</value>
>  </myParameter>
>  <myParameter name="output1" datatype="Int" direction="Out">
>    <value>2</value>
>  </myParameter>
></Root>
>
>Now to extend this with an external interface that will define its own
>parameter element this can be done in a separate schema that will
>include the base schema. Here is an example:
>
>External schema:
>-----------------
><?xml version="1.0" encoding="UTF-8"?>
><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>elementFormDefault="qualified" attributeFormDefault="unqualified">
>  <!-- Include the base schema -->
>  <xs:include schemaLocation="substGroup_base.xsd"/>
>
>  <!-- This is the type definition for the external parameter elements.
>This type must also derive from the "parameterBase" type so that the
>elements with this type can be used instead of the "parameterModel"
>element.-->
>  <xs:complexType name="externalParameterType">
>    <xs:complexContent>
>      <xs:extension base="parameterBase">
>        <xs:sequence>
>          <xs:element name="value" type="xs:string"/>
>          <xs:element name="external" type="xs:string"/>
>        </xs:sequence>
>        <xs:attribute name="externalAtt" type="xs:string" use="required"/>
>      </xs:extension>
>    </xs:complexContent>
>  </xs:complexType>
>
>  <!-- The external parameter elements are declared in the
>substitutionGroup of the "parameterModel" element and can hence be used
>instead of this element in the instance document.-->
>  <xs:element name="externalParameter" type="externalParameterType"
>substitutionGroup="parameterModel"/>
></xs:schema>
>
>In this external schema we have defined a new type that defines the
>external parameter elements (here called "externalParameter"). Since
>these elements can be used instead of the "parameterModel" elements in
>the instance document an instance that conforms to this schema can look
>like this:
>
><?xml version="1.0" encoding="UTF-8"?>
><Root>
>  <myParameter name="input1" datatype="Int" direction="In">
>    <value>1</value>
>  </myParameter>
>  <myParameter name="output1" datatype="Int" direction="Out">
>    <value>2</value>
>  </myParameter>
>  <externalParameter name="ext1" externalAtt="whatever">
>    <value>3</value>
>    <external>55</external>
>  </externalParameter>
></Root>
>
>This is made possible becuase the externalParameter element is declared
>to be in the substitutionGroup of the parameterModel element.
>
>I'm not sure if this match your design criteria but it seems it would
>fit in well with your description above. The drawback with this method
>is that all the elements involved in the substitutionGroup must be
>declared as global elements.
>For more information on substitutionGroups see [1].
>
>Hope this was of some help,
>Cheers,
>/Eddie
>
>[1] http://www.w3.org/TR/xmlschema-0/#SubsGroups
>
>  
>

Received on Thursday, 8 August 2002 20:28:12 UTC