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"