I have two xsd files. 1st file is common.xsd and the other is node.xsd. Both node.xsd and common.xsd share the same targetNamespace. common.xsd references an element defined in node.xsd using ref attribute. However, node.xsd is NOT included in common.xsd either using include or import. But the XML that I validate using these xsd files, passes the validation (Tried all corner usecases).
I wonder how this is possible. Is this because, they share the same namespace? Also is referencing an element without including/importing legal in XSD?
EDIT:
Simplified Code Snippets(The actual xsd’s are much more complex and they are written in this format for bigger reason):
common.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:my="my-namespace"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
targetNamespace="my-namespace"
elementFormDefault="qualified">
<xsd:element name="common" type="my:commonType" />
<xsd:complexType name="commonType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="my:node"/>
<!-- few other elements -->
</xsd:choice>
</xsd:complexType>
</xsd:schema>
node.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:my="my-namespace"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
targetNamespace="my-namespace"
elementFormDefault="qualified">
<xsd:include schemaLocation=common.xsd"/>
<xsd:element name="node" type="my:nodeType"
substitutionGroup="my:common" />
<xsd:complexType name="nodeType">
<xsd:complexContent>
<xsd:extension base="my:commonType">
<!-- some 5-7 attributes -->
<xsd:anyAttribute/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
These xsd’s let me nest element within itself any number of times.
E.g
<my:node>
<my:node />
<my:node>
<my:node />
</my:node>
</my:node>
You can observe that my:node is referenced in common.xsd without including node.xsd. (Curious as to how this even works.)
I can make this look even more wicked… You can remove the
xsd:includeinnode.xsdand still validate your XML! Take a look at this Xerces API for how you could do it.The idea is that from a spec perspective, an XML Schema processor can resolve schema locations in many ways. It also means that some XSD files when looked at individually may not be valid due to dangling references, yet when put together through APIs like the one above, or custom resolvers (e.g. supporting “catalog” files) the result is an equivalent schema that is valid.
The way an XSD processor typically works, is that it puts together all the schema components that can be loaded through the references it can resolve, then it looks at the result as a whole, irrespective of where these components come from. In your case, node.xsd brings in common.xsd; the result is a valid schema, since all that is needed for components in
common.xsdcan be found among components already brought in bynode.xsd.In your case it is as if the inner content of the xsd:schema tag in
common.xsdreplaces thexsd:includeinnode.xsd. If you do that by hand, the result is correct, right?As I side note, I would point out that the snippets you’ve shown don’t illustrate the use of the
commonsubstitution group. As a reminder, you have to reference the head of the substitution group if you want you to get substitution going.