The W3C XML Schema specification (XSD) provides support for schema composition through include, import and redefine elements. For large models based on composition it is common to see a large number of XSD files described by complex graphs, sometimes with cycles and confusing redefinitions. To make things worse outside the "XSD circle", there are mainstream products which simply do not support include or redefine elements.
Many then ask how to combine XSD files using some sort of automation. Many solutions are based on XSLT, C# or Java; some XML Schema editors offer simple built-in functionality. More often than not, solutions work only with trivial scenarios, and fail to explain the limitations that come with the underlying approach.
This paper sets out to explore the subject of combining multiple XSD files and provide illustrations based on capabilities found in our QTAssistant product. It also assumes the most common XSD file format encountered in the real world, that is an XML document where the root is an {http://www.w3.org/2001/XMLSchema}schema element.
The xsd:schema Element
The schema element is the root element of an XSD file. It supports a number of attributes; the highlighted ones are considered to play an important role in combining XSD files, and must be always accounted; others, such as id and xml:lang, can mostly be ignored but consider this fair warning, it would be up to you to understand if this information has relevance in your environment.
<schema
attributeFormDefault = (qualified | unqualified) : unqualified
blockDefault = (#all | List of (extension | restriction | substitution)) : ''
elementFormDefault = (qualified | unqualified) : unqualified
finalDefault = (#all | List of (extension | restriction | list | union)) : ''
id = ID
targetNamespace = anyURI
version = token
xml:lang = language
{any attributes with non-schema namespace . . .}>
Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
</schema>
![]() |
An XSD file can only target one XML namespace since there is only one targetNamespace attribute per XSD file. |
Secondly, include is different than import:
![]() |
An include must reference an XSD file that has the same target namespace, OR no target namespace definition at all. |
![]() |
An import must reference an XSD file that has a different target namespace. |
Therefore:
![]() |
A multi-namespace set of schema files must be composed from several XSD files. |
The minimum number of XSD files is a function of existence (TRUE/FALSE) of global elements (that can show as roots in XML documents) without a namespace, and the number of other namespaces:
![]() |
TRUE: 1 (for an XSD with no target namespace definition) + the number of other referenced XML namespaces; FALSE: the number of other referenced XML namespaces. |
It is important to remember the difference between a global element without a namespace, and a local element (contained by another element) without namespace; the same goes for attributes. From an XSD authoring perspective, this distinction can be controlled using two mechanisms:
- Through defaults at the schema file level, using the elementFormDefault and attributeFormDefault attributes of the schema element.
- Local overrides, using the form attribute when applied to an element or attribute local definition.
XSD files composed using include make them candidates for combining all into one XSD file. But things get tricky when different values are used for the schema element attributes we've highlighted above.
Simple Scenario: Strongly Connected XSD
A strongly connected XSD is a file from which it is possible to reach any other referenced XSD, by traversing external references. The diagram below shows a simple example of a typical layout; The only strongly connected XSD file is br-2.xsd

(Click to Enlarge)
Complex Scenario: Combining XSDs with different global settings
As an example, the form of elements and attributes can be controled using two mechanisms:
- Globally, through elementFormDefault and attributeFormDefault attributes of the schema element.
- Locally, using the form attribute that applies to an element or attribute definition.
XSD files composed using include are candidates for combining all into one XSD file; things get tricky when different values are used for the schema element attributes we've highlighted above that deal with the form of elements of attributes, or defaults for block and final.
To demonstrate a case where combining XSDs typically fails, the following XSD files were crafted.
BaseXsd
<?xml version="1.0" encoding="utf-8"?> <!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)--> <xsd:schema xmlns="urn:tempuri-org" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="urn:tempuri-org" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="reused"> <xsd:complexType> <xsd:sequence> <xsd:element name="some1" type="xsd:string"/> <xsd:element name="some2" type="xsd:string"/> <xsd:element ref="someref"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="someref" type="xsd:int"/> </xsd:schema>
TopXsd
<?xml version="1.0" encoding="utf-8"?> <!--XML Schema generated by QTAssistant/XSR Module (http://www.paschidev.com)--> <xsd:schema xmlns="urn:tempuri-org" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="urn:tempuri-org" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:include schemaLocation="BaseXsd.xsd"/> <xsd:element name="root"> <xsd:complexType> <xsd:sequence> <xsd:element ref="reused"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>