Re: restriction question

Hi Calvin,

> Thanks, Dare. I tried setting elementFormDefault to unqualified (I
> think you meant either/or with the two suggestions), and then Xerces
> complains that:
>
> Error: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a:
> Invalid content starting with element 'State'. The content must
> match '(("":State),("":Country))'.
>
> This is because of the default namespace, right?

I *think* (though I'm not certain) that this is an error message about
the *instance* document; you have the State and Country elements in
the instance document in the (default) target namespace of your second
schema when, to be valid against the schema, they must be in *no*
namespace (i.e. have no prefix and not be in the scope of a default
namespace declaration that sets the default namespace to anything
other than the empty string). In other words, it would need to look
like:

  <s:Address xmlns:s="http://www.test.com/sample2">
    <State>...</State>
    <Country>...</Country>
  </s:Address>

> What I would like to do is restrict a type from a foreign
> schema/namespace -- which I have no control over -- in a namespace
> that I do have control over, and I would like to have the default
> namespace be equal to the target namespace in my schema. Is this
> possible? If I have understood you properly, then this isn't
> possible if the foreign namespace schema has elementFormDefault set
> to 'qualified'. Is this correct? Do I have to not use the
> xmlns=targetNamespace?

What you would like is:

  <Address xmlns="http://www.test.com/sample2">
    <State>...</State>
    <Country>...</Country>
  </Address>

The trouble is that your original foreign schema (before you changed
the elementFormDefault) defines an Address type as looking something
like:

  <Address xmlns="http://www.test.com/sample">
    <Street>...</Street>
    <State>...</State>
    <Country>...</Country>
  </Address>

You might think that these look the same, but actually the difference
in namespace makes all the difference in the world. As far as the XML
Schema processor is concerned, the foreign schema might as well have
specified the AddressType as:

  <Address xmlns="http://www.test.com/sample">
    <Foogle>...</Foogle>
    <Barble>...</Barble>
    <Bazzle>...</Bazzle>
  </Address>

for all the similarity that it shares with the SimplerAddressType, in
which the State and Country elements are in a completely different
namespace.

You have to decide what you want your instance document to look like,
and then create the schema around that. If you want your instance
document to look like:

  <Address xmlns="http://www.test.com/sample2">
    <State>...</State>
    <Country>...</Country>
  </Address>

then what you're saying is that you can use
{http://www.test.com/sample2}State instead of
{http://www.test.com/sample}State and
{http://www.test.com/sample2}Country instead of
{http://www.test.com/sample}Country. To say that in XML Schema, you
need to make {http://www.test.com/sample2}State a member of
{http://www.test.com/sample}State's substitution group, which means
that both need to be declared at the top level and referred to from
within the content model.

In other words, try the following:

Foreign schema:

<xs:schema targetNamespace="http://www.test.com/sample"
           xmlns="http://www.test.com/sample"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
           
<xs:complexType name="AddressType">
  <xs:sequence>
    <xs:element ref="Street" minOccurs="0" />
    <xs:element ref="State" minOccurs="0" />
    <xs:element ref="Country" minOccurs="0" />
  </xs:sequence>
</xs:complexType>

<xs:element name="Street" type="xs:string" />
<xs:element name="State" type="xs:string" />
<xs:element name="Country" type="xs:string" />

</xs:schema>

Your schema:

<xs:schema targetNamespace="http://www.test.com/sample2"
           xmlns="http://www.test.com/sample2"
           xmlns:s="http://www.test.com/sample"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">

<xs:import namespace="http://www.test.com/sample"
           schemaLocation="sample.xsd" />
           
<xs:complexType name="SimplerAddressType">
  <xs:complexContent>
    <xs:restriction base="s:AddressType">
      <xs:sequence>
        <xs:element ref="State" />
        <xs:element ref="Country" />
      </xs:sequence>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

<xs:element name="State" substitutionGroup="s:Street" />
            
<xs:element name="Country" substitutionGroup="s:Country" />

</xs:schema>

If the foreign schema had no target namespace, you'd have a much
easier time of it since schemas with no target namespace have the
peculiar properly of being adopted into the target namespace of
whatever schema they're included into. So another possible pairing
would be:

Foreign schema:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
           
<xs:complexType name="AddressType">
  <xs:sequence>
    <xs:element name="Street" type="xs:string" minOccurs="0" />
    <xs:element ref="State" type="xs:string" minOccurs="0" />
    <xs:element ref="Country" type="xs:string" minOccurs="0" />
  </xs:sequence>
</xs:complexType>

</xs:schema>

Your schema:

<xs:schema targetNamespace="http://www.test.com/sample2"
           xmlns="http://www.test.com/sample2"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">

<xs:include schemaLocation="sample.xsd" />
           
<xs:complexType name="SimplerAddressType">
  <xs:complexContent>
    <xs:restriction base="AddressType">
      <xs:sequence>
        <xs:element name="State" type="xs:string" />
        <xs:element name="Country" type="xs:string" />
      </xs:sequence>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

</xs:schema>

Cheers,

Jeni

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

Received on Tuesday, 23 July 2002 04:49:05 UTC