I'm trying to mimic a relational database structure using XML.
(Just in case anyone is wondering why, my reasons for using XML are: (1) The total amount of data is expected to be small, (2) I need non-programmers to be able to edit some of the input tables, and (3) I want the installation process to be as simple as possible (i.e., no database servers). Also, (4) the people editing the input tables won't have MS Access.)
I expect a large chunk of the database structure to be reused on several projects, so I set out to write two schema (XSD) files. The first would contain definitions for all the basic/reusable tables, while the second would contains definitions for the tables specific to the particular application. Let's say these two files are called Basic.xsd and Specific.xsd.
The good news: I have written my two schema files, and they seem to work as I intended.
The bad news: I wasn't able to write them the way I wanted to. Specifically, I wasn't able to separate the keys/keyrefs for basic data from the keys/keyrefs for the specific data as I had planned. The only thing I could get to work was to lump all keys/keyrefs under a single element in Specific.xsd.
Let me paste in the files here so you can see what I'm talking about.
Basic.xsd
<?xml version="1.0"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:complexType name="tables">
<xs:sequence>
<xs:element name="basic1Table" type="basic1Table" />
<xs:element name="basic2Table" type="basic2Table" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="basic1Table">
<xs:sequence>
<xs:element name="basic1" type="basic1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="basic2Table">
<xs:sequence>
<xs:element name="basic2" type="basic2" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="basic1">
<xs:sequence>
<xs:element name="id" type="xs:int" />
<xs:element name="value" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="basic2">
<xs:sequence>
<xs:element name="id" type="xs:int" />
<xs:element name="value" type="xs:string" />
<xs:element name="basic1Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Specific.xsd
<?xml version="1.0"?>
<xs:schema
xmlns="example"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="example"
targetNamespace="example"
elementFormDefault="qualified">
<xs:redefine schemaLocation="Basic.xsd">
<xs:complexType name="tables">
<xs:complexContent>
<xs:extension base="tables">
<xs:sequence>
<xs:element name="specific1Table" type="specific1Table" />
<xs:element name="specific2Table" type="specific2Table" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
<xs:element name="tables" type="tables">
<xs:key name="basic1Key"> <!-- Should be in Basic.xsd -->
<xs:selector xpath="tns:basic1Table/tns:basic1" />
<xs:field xpath="tns:id" />
</xs:key>
<xs:key name="basic2Key"> <!-- Should be in Basic.xsd -->
<xs:selector xpath="tns:basic2Table/tns:basic2" />
<xs:field xpath="tns:id" />
</xs:key>
<xs:key name="specific1Key">
<xs:selector xpath="tns:specific1Table/tns:specific1" />
<xs:field xpath="tns:id" />
</xs:key>
<xs:key name="specific2Key">
<xs:selector xpath="tns:specific2Table/tns:specific2" />
<xs:field xpath="tns:id" />
</xs:key>
<xs:keyref name="basic2ToBasic1KeyRef" refer="basic1Key"> <!-- Should be in Basic.xsd -->
<xs:selector xpath="tns:basic2Table/tns:basic2" />
<xs:field xpath="tns:basic1Id" />
</xs:keyref>
<xs:keyref name="specific2ToSpecific1KeyRef" refer="specific1Key">
<xs:selector xpath="tns:specific2Table/tns:specific2" />
<xs:field xpath="tns:specific1Id" />
</xs:keyref>
<xs:keyref name="specific2ToBasic1KeyRef" refer="basic1Key">
<xs:selector xpath="tns:specific2Table/tns:specific2" />
<xs:field xpath="tns:basic1Id" />
</xs:keyref>
</xs:element>
<xs:complexType name="specific1Table">
<xs:sequence>
<xs:element name="specific1" type="specific1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="specific2Table">
<xs:sequence>
<xs:element name="specific2" type="specific2" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="specific1">
<xs:sequence>
<xs:element name="id" type="xs:int" />
<xs:element name="value" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="specific2">
<xs:sequence>
<xs:element name="id" type="xs:int" />
<xs:element name="value" type="xs:string" />
<xs:element name="basic1Id" type="xs:int" />
<xs:element name="specific1Id" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Sample XML file that validates successfully
<?xml version="1.0" encoding="utf-8"?>
<tables
xmlns="example"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="example Specific.xsd">
<basic1Table>
<basic1>
<id>1</id>
<value>value1</value>
</basic1>
<basic1>
<id>2</id>
<value>value2</value>
</basic1>
<basic1>
<id>3</id>
<value>value3</value>
</basic1>
</basic1Table>
<basic2Table>
<basic2>
<id>1</id>
<value>value1</value>
<basic1Id>1</basic1Id>
</basic2>
<basic2>
<id>2</id>
<value>value2</value>
<basic1Id>2</basic1Id>
</basic2>
<basic2>
<id>3</id>
<value>value3</value>
<basic1Id>3</basic1Id>
</basic2>
</basic2Table>
<specific1Table>
<specific1>
<id>1</id>
<value>value1</value>
</specific1>
<specific1>
<id>2</id>
<value>value2</value>
</specific1>
<specific1>
<id>3</id>
<value>value3</value>
</specific1>
</specific1Table>
<specific2Table>
<specific2>
<id>1</id>
<value>value1</value>
<basic1Id>1</basic1Id>
<specific1Id>1</specific1Id>
</specific2>
<specific2>
<id>2</id>
<value>value2</value>
<basic1Id>2</basic1Id>
<specific1Id>2</specific1Id>
</specific2>
<specific2>
<id>3</id>
<value>value3</value>
<basic1Id>3</basic1Id>
<specific1Id>3</specific1Id>
</specific2>
</specific2Table>
</tables>
So, the keys basic1Key and basic2Key and the keyref basic2ToBasic1KeyRef are in Specific.xsd. I'd like to figure out a way to move them to Basic.xsd, while keeping all the keys/keyrefs involving "specific" data in Spcific.xsd. The problem is that keys/keyrefs are tied to elements, not to types. So, I can't place the keys/keyrefs inside the xs:complexType definitions where they belong (at least in my mind).
One thought I had was to separate the "tables" element into two separate elements: basicTables and specificTables, but there is an added complication here that makes that difficult (impossible?). Notice the keyref, specific2ToBasic1KeyRef. This creates a link between the specific2 table and the basic1 table. So, I would need this keyref to "jump across" elements, which I don't think is possible.
To summarize, how can I make it so that all the table definitions, keys, and keyrefs for "basic" data are stored in Basic.xsd, while all additional definitions needed for the specific implementation are stored in Specific.xsd? If it's not possible and what I've pasted in here is as good as I'm going to get, that would be nice to know too.
Thanks for your help!
-Dan