Re: Extensibility Question

Thanks Eddie, that certainly was helpful. I'm not sure it's the right
approach in my situation, but it definitiely improves my understanding of
how to use substitution groups! :-) 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.
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 Wednesday, 7 August 2002 11:44:09 UTC