Article : How to combine multiple XSDs into minimum number of files
How to combine multiple XSDs into minimum number of files
The W3C XML Schema specification (XSD) provides support for schema composition in the form of include, import and redefine elements. These features allow for content reuse, but can also lead to poor readability and complex graphs, sometimes with cycles and confusing redefinitions. To make things interesting, some mainstream products simply do not support include or redefine elements.
Many then ask how to combine XSD files, ideally using some sort of automation; many more answer with various solutions, varying from XSLT, C# or Java, to functionality built-in XML Schema editors. More often than not, the solutions work only with common scenarios, and fail to disclaim, explain, or both, the limitations that come with their approaches.
This sets out to explore the subject of combining multiple XSD files; illustrations are based on QTAssistant.
The xsd:schema Element
The schema element is the root element of any XSD file; the highlighted attributes have an important role in how XSD files may (or not) be combined.
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*)*)
Simple Scenario: Use a 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
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.xsd Copy Code
targetNamespace="urn:tempuri-org" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
TopXsd.xsd Copy Code
elementFormDefault="qualified" targetNamespace="urn:tempuri-org" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
An example of a C# script posted on Technet will generate the following XSD:
BadResult.xsd Copy Code
elementFormDefault="qualified" targetNamespace="urn:tempuri-org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
What we usually recommend for a sanity check is one of the next two things, depending on available resources.
One is to have a valid XML file (master XML), generated with sufficient coverage from the "gold copy" XSDs, validated using the new XSD.
Original XSDs Valid XML.xsd Copy Code
some11
some21
1
If we use the BadResult.xsd to validate the master XML, an error is shown.
Error occurred while loading [], line 5 position 4
The element 'reused' in namespace 'urn:tempuri-org' has invalid child element 'some1'. List of possible elements expected: 'some1' in namespace 'urn:tempuri-org'.
Document1.xml is invalid.
Another approach is to use XSD compare tooling. QTAssistant's XSD compare shows that differences were found.
XSD Compare Diff Report
The TopXsd file can be opened in the XSD editor; from the XSD Tools tab, invoke the Collapse command.
A quick look at the generated XSD shows the important differences which account for the difference there was between the elementFormDefault attributes: the form="unqualified" attributes which now decorate elements some1 and some2.
RefactoredXsd.xsd Copy Code
Generated from "Set1" under "dummy"