XSD with elements from other namespace

poke picture poke · Jun 20, 2011 · Viewed 51.2k times · Source

I have two XSDs that are definining different documents. Say A.xsd defines an element ElementA as the root, with some complex rules. Now B.xsd defines an element ElementB that is supposed to use ElementA somewhere in between.

For example I want the XML file for ElementB look like this:

<?xml version="1.0" encoding="utf-8"?>
<ElementB xmlns="http://example.com/namespace/for/ElementB">
  <foo>Bla</foo>
  <bar>Blub</bar>
  <ElementA xmlns="http://example.com/namespace/for/ElementA">
    <!-- ... -->
  </ElementA>
</ElementB>

Then B.xsd could look like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://example.com/namespace/for/ElementB" targetNamespace="http://example.com/namespace/for/ElementB" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="ElementB">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="foo" type="xs:string" />
        <xs:element name="bar" type="xs:string" />

        <!-- And now I want to include ElementA somehow -->
        <xs:element name="ElementA" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The thing is that I don‘t really want to clone the specification of ElementA into B.xsd, as there are also documents, that just have ElementA as the root (i.e. ElementB is some kind of container document).

So, how can I allow ElementA within ElementB while completely building on top of the already existent XSD?

Answer

daveaglick picture daveaglick · Jun 20, 2011

There are actually two different ways to compose XML Schema documents: <xs:import> and <xs:include>. xs:include is intended to be used when the namespace of the containing document is the same as the one being referenced, so it's not quite what you're looking for. xs:import is better for your situation when you need to reference all (or a subset) of elements in the referenced schema and they're in a different target namespace. There's a question here on the differences: What's the difference between xsd:include and xsd:import?.

Anyway, back to this specific question. What you probably want is something like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema 
    xmlns="http://example.com/namespace/for/ElementB"
    targetNamespace="http://example.com/namespace/for/ElementB"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    xmlns:ea="http://example.com/namespace/for/ElementA">
 <xs:import namespace="http://example.com/namespace/for/ElementA" schemaLocation="A.xsd" /> 
 <xs:element name="ElementB">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="foo" type="xs:string" />
    <xs:element name="bar" type="xs:string" />
    <!-- This introduces a element named ElementA that uses the ComplexType ea:ElementA defined in A.xsd -->
    <xs:element name="ElementA" type="ea:ElementA" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Though you'll need A.xsd to create a complex type for ElementA that you can use in B.xsd as shown.

This arcticle has some good information/examples and includes a discussion of some of the different composability strategies: http://www.xfront.com/ZeroOneOrManyNamespaces.html