Re: Re xsd:string not validly derived

Hi JK,

> Well I was writing a schema for the state to either integer or
> string...But as a matter of fact I came down to check how to make it
> work with string itself and move on to add the different
> cases..Infact my orginal schema was like
>
> <xsd:simpleType>
>   <xsd:restriction>
>    <xsd:simpleType>
>      <xsd:union memberTypes='xsd:integer xsd:string'/>
>    </xsd:simpleType>
>    <xsd:pattern value='1'/>
>    <xsd:pattern value='2'/>
>    <xsd:pattern value='(A|ZK)'/>
>   </xsd:restriction>
>  </xsd:simpleType>

You should use xsd:enumeration rather than patterns that simply
enumerate the possible values. In other words, this would be better
as:

  <xsd:simpleType>
    <xsd:restriction>
      <xsd:simpleType>
        <xsd:union memberTypes="xsd:integer xsd:string" />
      </xsd:simpleType>
      <xsd:enumeration value="1" />
      <xsd:enumeration value="2" />
      <xsd:enumeration value="A" />
      <xsd:enumeration value="ZK" />
    </xsd:restriction>
  </xsd:simpleType>

The reason this is better is that it's easier for programs such as
authoring tools to pull out the possible values of the simple type and
use them to assist authoring (e.g. to supply a drop-down list that
enables the writer to choose one of '1', '2', 'A' or 'ZK'). Also, for
the validator, I imagine it's slightly easier (quicker) to test
equality between values (which you can do with an enumeration) than it
is to test against a regular expression (which you have to do if you
specify the options as a pattern).
  
> But then I had to add the soap encoding attribute too and that is
> when I couldn't figurre out a way to do it...

You were doing that fine in the example schema you sent. Since the
element needs an attribute, it has to be a complex type; since it has
only text as its content, it has to have simple content, so you want
to extend the simple type that you already have to add an attribute to
it:

  <xsd:complexType>
    <xsd:simpleContent>
      <xsd:extension>
        <xsd:simpleType>
          <xsd:restriction>
            <xsd:simpleType>
              <xsd:union memberTypes="xsd:integer xsd:string" />
            </xsd:simpleType>
            <xsd:enumeration value="1" />
            <xsd:enumeration value="2" />
            <xsd:enumeration value="A" />
            <xsd:enumeration value="ZK" />
          </xsd:restriction>
        </xsd:simpleType>
        <xsd:attribute ref="soapEnv:encodingStyle" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

But if you do this, you cannot say that the state element in the
instance is a "xsd:string" because it's not -- it's a complex type (an
anonymous one since you've nested the definition within the element
declaration for the state element). As I said before, I don't know why
you're trying to use xsi:type to say that the state element's content
is a xsd:string anyway -- the validator knows that already by looking
at the value that it contains and the type declared for the element in
the schema.

If you want to use xsi:type within the instance document to indicate
whether the content of the state element is a string or an integer,
then I think you're out of luck. The only route that I can see would
be to create a complex type hierarchy with a base type that allows
both strings and integers and then create two derived types that allow
only integers and only strings respectively. For example:

<xsd:simpleType name="string-values">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="A" />
    <xsd:enumeration value="ZK" />
  </xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="integer-values">
  <xsd:restriction base="xsd:integer">
    <xsd:enumeration value="1" />
    <xsd:enumeration value="2" />
  </xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="string-or-integer-values">
  <xsd:union memberTypes="integer-values string-values" />
</xsd:simpleType>

<xsd:complexType name="string-or-integer-with-encodingStyle">
  <xsd:simpleContent>
    <xsd:extension base="string-or-integer-values">
      <xsd:attribute ref="soapEnv:encodingStyle" />
    </xsd:extension>
  </xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="string-with-encodingStyle">
  <xsd:simpleContent>
    <xsd:restriction base="string-or-integer-with-encodingStyle">
      <xsd:simpleType>
        <xsd:restriction base="string-values" />
      </xsd:simpleType>
    </xsd:restriction>
  </xsd:simpleContent>
</xsd:complexType>

<xsd:complexType name="integer-with-encodingStyle">
  <xsd:simpleContent>
    <xsd:restriction base="string-or-integer-with-encodingStyle">
      <xsd:simpleType>
        <xsd:restriction base="integer-values" />
      </xsd:simpleType>
    </xsd:restriction>
  </xsd:simpleContent>
</xsd:complexType>

You could then say that the your state element was of the type
"string-with-encodingStyle" or "integer-with-encodingStyle".

However, I don't think that the above is a legal XML Schema. It passes
XSV and Xerces-J validation; Xerces-C++ thinks the schema is OK but
complains if the state element has an encodingStyle attribute; MSXML
rejects the schema saying the "integer-with-encodingStyle" isn't a
valid restriction of "string-or-integer-with-encodingStyle". Reading
through the XML Schema Structures Rec, I think that MSXML is correct
-- for integer-with-encodingStyle to be validly derived from
string-or-integer-with-encodingStyle, the atomic simple type
definition it contains (an unrestricting restriction of
integer-values) has to be a valid restriction of the union
string-or-integer-values simple type, and atomic simple type
definitions can only be derived by restriction from other atomic (or
built-in primitive) types (according to
http://www.w3.org/TR/xmlschema-1/#cos-st-restricts).

There are ways round it, I think, but none that I can think of are
particularly pleasant or retain the correct semantics. Perhaps someone
else can come with something that I've missed.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

Received on Sunday, 14 July 2002 07:34:11 UTC