3

I have an xml document that looks something like below (resources.xml), with a corresponding xml-schema (resources.xsd). This xml document is manually maintained (i.e adding/removing/editing resource elements). In total there are maybe 500-1000 resource elements. Each resource can be of either variantX or variantY (in "real life", there are a few more variants).

I would like to split up the xml document into several xml documents. One xml document for each variant (X and Y in this case), with a corresponding new xml-schemas. The xml schemas for each variant, should extend the original schema and only add a "hardcoded" (fixed?) value for it's "variant" attribute.

Reason: To avoid repeating the "variant" attribute within each resource element.

Is this possible? What would the xml-schemas for each variant look like? What changes needs to be done in resources.xsd?

Any other suggestions are also welcomed :)

resources.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="resources.xsd">
        <resource name="res00" variant="X" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
        <resource name="res01" variant="X" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
        <resource name="res02" variant="Y" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
        <resource name="res03" variant="Y" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
    </resources>

resources.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:rb="http://example.org/resourcebase">

    <xs:complexType name="property">
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="value" type="xs:string" />
    </xs:complexType>

    <xs:complexType name="resource">
        <xs:sequence>
            <xs:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required" />
        <xs:attribute name="variant" type="xs:string" use="required" />
    </xs:complexType>

    <xs:element name="resources">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="resource" type="resource" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Here's how I picture this. One xml document for variant=X, which referrers to resourcesX.xsd. No need to add the "variant" attribute, as it is added by the referred resourcesX.xsd.

resourcesX.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="resourceX.xsd">
        <resource name="res00" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
        <resource name="res01" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
    </resources>

Another xml document for variant=Y, which referrers to resourcesY.xsd. No need to add the "variant" attribute, as it is added by the referred resourcesY.xsd.

resourcesY.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="resourceY.xsd">
        <resource name="res02" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
        <resource name="res03" >
            <property name="propA" value="..." />
            <property name="propB" value="..." />
        </resource>
    </resources>

Can resourceX.xsd and resourceY.xsd extend the resources.xsd? If so, what would they look like? any changes needed to be made in resources.xsd?

Thanks! /Alex

etxalpo
  • 1,146
  • 1
  • 14
  • 25

2 Answers2

2

To split this into multiple schema files, you'll first need to modify your base schema to include only the types and elements that will be shared, and will need to refine those elements to allow extension (or restriction in your derived schemas). In your case, it looks like the property type will be reused and the resource type will be restricted, so the base schema would look something like:

resources.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:complexType name="property">
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="value" type="xs:string" />
    </xs:complexType>

    <xs:complexType name="resource">
        <xs:sequence>
            <xs:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required" />
        <xs:attribute name="variant" type="xs:string"/>
    </xs:complexType>

</xs:schema>

Note in resource, the variant attribute no longer is use="required", since your goal is that you will not want that to be required in your instance documents.

For the 'X' variant of the schema, you'll need to include the resources.xsd schema, and will need to define your restricted resourceX element and the containing resources element.

resourceX.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:include schemaLocation="resources.xsd"/>

    <xs:complexType name="resourceX">
        <xs:complexContent>
            <xs:restriction base="resource">
                <xs:sequence>
                    <xs:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
                </xs:sequence>
                <xs:attribute name="name" type="xs:string" use="required" />
                <xs:attribute name="variant" type="xs:string" fixed="X"/>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:element name="resources">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="resource" type="resourceX" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

The xs:include statement will include your previously defined schema. The new types resourceX defines your restriction on the resource element, and associates the fixed value X with variant. Finally the resources element is redefined to be a collection of elements of type resourceX instead of resource.

resourceY.xsd would be defined in a similar manner to resourceX.xsd.

DRH
  • 7,868
  • 35
  • 42
1

It sounds like your goal is to only have resources of a single variant in a particular file, in that case, instead of removing the variant attribute, would it make sense to move it to the root resources type? This would allow the document structure to retain the information about which variant is being represented, but also ensure that all of the resource elements in a particular file are associated with a particular variant. Something like:

resources.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:complexType name="property">
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="value" type="xs:string" />
    </xs:complexType>

    <xs:complexType name="resource">
        <xs:sequence>
            <xs:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required" />
    </xs:complexType>

    <xs:element name="resources">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="resource" type="resource" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="variant" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

and instance document:

resourceX.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="resources.xsd"
        variant="X">
    <resource name="res00" >
        <property name="propA" value="..." />
        <property name="propB" value="..." />
    </resource>
    <resource name="res01" >
        <property name="propA" value="..." />
        <property name="propB" value="..." />
    </resource>
</resources>
DRH
  • 7,868
  • 35
  • 42