overriding minOccurs from a group

376 views Asked by At

I have a situation where there is a base type that I don't "own" and it allows all child elements to be optional. From a general business perspective this makes sense. For example, say it was:

<xs:complexType name="BaseType">
    <xs:sequence>
        <xs:element name="id" type="xs:string" minOccurs="0"/>
        <xs:element name="name" type="xs:string" minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

An instance of this type will be contained in a containing type that my process uses.

<xs:complexType name="MyType">
    <xs:sequence>
        <xs:element name="Widget" type="BaseType"/>
        ...other stuff...
    <xs:sequence>
</xs:complexType>

However, for my particular purposes, I need the 'id' element on a BaseType to be present always. I can enforce this in the code that consumes it, of course, but is there some way to represent this in the xsd?

EDIT I forgot one other. There's another, similar situation, where the elements I'm using are in a group rather than a base type.

<xs:group name="Address-Group">
    <xs:sequence>
        <xs:element name="street" type="xs:string" minOccurs="0"/>
        <xs:element name="city" type="xs:string" minOccurs="0"/>
        ...etc....
    </xs:sequence>
</xs:group>

If I employ one of these in MyType, I'd have the same question about trying to override minOccurs for something like 'city'.

1

There are 1 answers

1
Petru Gardea On BEST ANSWER

Assuming that for my particular purposes, I need the 'id' element on a BaseType to be present always you really meant always, then you can apply a redefine such as the one below:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XSR Module (http://www.paschidev.com)-->
<xsd:schema xmlns="http://tempuri.org/XMLSchema.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:redefine schemaLocation="xsd-overriding-minoccurs-from-a-group.xsd">
        <xsd:complexType name="BaseType">
            <xsd:complexContent>
                <xsd:restriction base="BaseType">
                    <xsd:sequence>
                        <xsd:element name="id" type="xsd:string"/>
                        <xsd:element name="name" type="xsd:string" minOccurs="0"/>
                    </xsd:sequence>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
        <xsd:group name="Address-Group">
            <xsd:sequence>
                <xsd:element name="street" type="xsd:string"/>
                <xsd:element name="city" type="xsd:string" minOccurs="0"/>
            </xsd:sequence>
        </xsd:group>
    </xsd:redefine>
</xsd:schema>

The thing is, redefine works "always", i.e. in all instances where a BaseType is used, the redefined definition will take precedence. In other words, there is no mechanism built in XSD where you might be able to pick and choose your context, unless you move to XSD 1.1 where you wouldn't then need redefine but some sort of assertion. The problem is, I would venture to say that XSD 1.1 is even less supported than XSD 1.0 (across platforms rather than on a particular one that might happen to support both anyway, such as Saxon or Xerces).

An XML such as this is valid:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<paschidev.dummy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BaseType" xmlns="http://tempuri.org/XMLSchema.xsd">
    <id>id1</id>
    <name>name1</name> 
</paschidev.dummy>

Whereas this one will fail:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<paschidev.dummy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BaseType" xmlns="http://tempuri.org/XMLSchema.xsd">
    <name>name1</name> 
</paschidev.dummy>

With the following error message (.NET based):

Error occurred while loading [], line 4 position 3
The element 'paschidev.dummy' in namespace 'http://tempuri.org/XMLSchema.xsd' has invalid child element 'name' in namespace 'http://tempuri.org/XMLSchema.xsd'. List of possible elements expected: 'id' in namespace 'http://tempuri.org/XMLSchema.xsd'.

or this (Java based):

Error while loading [], line 4 position 8
cvc-complex-type.2.4.a: Invalid content was found starting with element 'name'. One of '{"http://tempuri.org/XMLSchema.xsd":id}' is expected.

The redefine works well with XSD-aware XML processors. However, some XSD to code binding frameworks, or database engines with built-in XSD support may cough on this one.