Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use type from xsd imported from import

Tags:

xsd

Given a top level xsd that imports a second level which in turn imports a third, is it possible to use a type from the third in the first? Or does the first have to import the third directly?

like image 233
cellige Avatar asked Dec 06 '12 02:12

cellige


2 Answers

Good question! From reading the spec, I can't really tell. It doesn't explicitly address the issue of transitive imports explicitly.

In the Primer (part 0), they only talk about one level of importing: http://www.w3.org/TR/xmlschema-0/#import

In Structure (part 1), it also only defines direct importing http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#composition-schemaImport Since it talks about "a means of addressing such foreign component" (which I think means namespace), maybe it's reasonable to assume that an explicit way of addressing imported schemas is necessary - in other words, an explicit namespace in an import is needed for each one.

A google search shows that other people have also been confused by this issue:

  • http://xsd.stylusstudio.com/2002Apr/post00021.htm
  • http://xsd.stylusstudio.com/2005Mar/post05007.htm

What's of most concern about those posts is that different xsd processors have different behaviour - suggesting that the writers of the processors were also confused.

Although that may have changed since those posts (2002, 2005), the wisest course seems to be to avoid the issue, and just use direct imports, because this will work with all processors.

As I said: good question.


Here is a test, to check an xsd processor (of course, this won't guarantee that it will work for someone else using some other xsd processor...). I found that my favourite one (xmllint) does not allow transitive imports.

The test is three schemas: a.xsd imports b.xsd which in turn imports c.xsd; and a type defined in c.xsd is referenced from a.xsd:

<!-- a.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c="http://www.c.com" targetNamespace="http://www.a.com">
  <xsd:import namespace="http://www.b.com" schemaLocation="b.xsd"/>
<!--  UNCOMMENT FOR DIRECT IMPORT
  <xsd:import namespace="http://www.c.com" schemaLocation="c.xsd"/>
-->
  <xsd:element name="eg" type="c:TypeC"/>
</xsd:schema>

<!-- b.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:import namespace="http://www.c.com" schemaLocation="c.xsd"/>
</xsd:schema>

<!-- c.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.c.com">
  <xsd:simpleType name="TypeC">
      <xsd:restriction base="xsd:string"/>
  </xsd:simpleType>
</xsd:schema>


<!-- a.xml -->
<eg xmlns="http://www.a.com">hello world</eg>

$ xmllint --schema a.xsd a.xml  --noout
a.xsd:6: element element: Schemas parser error : Element
'{http://www.w3.org/2001/XMLSchema}element', attribute 'type': References from
this schema to components in the namespace 'http://www.c.com' are not allowed,
since not indicated by an import statement.
WXS schema a.xsd failed to compile

The error message is: References from this schema to components in the namespace 'http://www.c.com' are not allowed, since not indicated by an import statement., suggesting that the developers of xmllint at least are quite sure that imports are not transitive.

like image 135
13ren Avatar answered Oct 12 '22 11:10

13ren


If type is what you are talking about then .. It's <xs:Include> not <xs:Import> ..

And the answer is : Parser takes care of linking all XSDs together

see the example below:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <child>trial</child>
  <child2>trial2</child2>
  <trunk>
    <branch>1</branch>
    <branch>2</branch>
  </trunk>
  <specialchild>test</specialchild>
</root>

For the above XML I will design an XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:include schemaLocation="include multiple XSDs2.xsd"/>
  <xs:element name="root" type ="root"/>
  <xs:complexType name="root">
    <xs:sequence>
      <xs:element name="child" type="xs:string" />
      <xs:element name="child2" type="xs:string" />
      <xs:element name="trunk" type="trunk"/>
      <xs:element name="specialchild" type="specialchild"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

where type trunk is defined in import multiple XSDs2.xsd file and linked by using <xs:include> .. (which is residing in the same folder).. And the code looks like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:include schemaLocation="include multiple XSDs3.xsd"/>
  <xs:complexType name="trunk">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" name="branch" type="branch" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

and type branch is a simple type defined in include multiple XSDs3.xsd file, and the code looks like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:simpleType name="branch">
    <xs:restriction base="xs:string"/>
  </xs:simpleType>
  <xs:simpleType name="specialchild">
    <xs:restriction base="xs:string"/>
  </xs:simpleType>
</xs:schema>

*Now the tricky part is: specialchild is declared in XSD_1 where as defined in XSD_3 and these two XSDs are linked by XSD_2.. You can observe that parser by default takes care of linking all XSDs and treating them all as one! *

Hope this solves your question!

like image 28
InfantPro'Aravind' Avatar answered Oct 12 '22 11:10

InfantPro'Aravind'