Tagc
Tagc

Reputation: 9072

How can I allow an element to contain one of a choice of child elements OR a number?

I'm trying to develop an implementation of the Pipes and Filters pattern and I want to allow the user to specify the filters within a pipeline within a configuration file. XML is a good choice for this because it's a hierarchical language - pipelines can be specified by nesting XML elements corresponding to specific types of filters within one another.

I've tried defining a small number of filters and an "InputType" type definition containing an xsd:choice element to select between them. However, the choice element seems to only allow a choice between child elements, and not other possible kinds of data like xs:string or xs:decimal.

I currently have a schema like this:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="InputLinearScaleType">
        <xs:sequence>
            <xs:element name="Input" type="InputType"/>
            <xs:element name="Gain" type="InputType" minOccurs="0"/>
            <xs:element name="Offset" type="InputType" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="NumericLoggingFilterType">
        <xs:sequence>
            <xs:element name="Input" type="InputType" />
            <xs:element name="LogPath" type="xs:string" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="InputType">
        <xs:sequence>
            <xs:choice>
                <xs:element name="LinearScale" type="InputLinearScaleType" />
                <xs:element name="Logger" type="NumericLoggingFilterType" />
                <xs:element name="Constant" type="xs:decimal" />
                <xs:element name="SimulatedNumericSource" />
            </xs:choice>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="FilterExample" type="InputType" />
</xs:schema>

This allows me to validate something like this:

<FilterExample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///W:/Shared/XML Schemas/schemaFilterTemp.xsd">
    <Logger>
        <Input>
            <LinearScale>
                <Input>
                    <SimulatedNumericSource/>
                </Input>
                <Gain>
                    <Constant>5</Constant>
                </Gain>
                <Offset>
                    <Constant>11</Constant>
                </Offset>
            </LinearScale>
        </Input>
        <LogPath>/dev/null</LogPath>
    </Logger>
</FilterExample>

However, what I'd like is to be able to validate something like the following instead:

<FilterExample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:///W:/Shared/XML Schemas/schemaFilterTemp.xsd">
    <Logger>
        <Input>
            <LinearScale>
                <Input>
                    <SimulatedNumericSource/>
                </Input>
                <Gain>5</Gain>
                <Offset>11</Offset>
            </LinearScale>
        </Input>
        <LogPath>/dev/null</LogPath>
    </Logger>
</FilterExample>

This would require the schema to allow for a number of elements which would be interpreted as specify types of numeric source filters or a decimal number.

Is there a way I can do this?

Upvotes: 0

Views: 57

Answers (1)

Michael Kay
Michael Kay

Reputation: 163587

No, there's no clean way to do this. In XSD 1.1 you could define mixed content and then use an assertion to force the content to be one thing or the other, but even then the content would be typed as a string rather than a number.

Generally, XSD isn't designed on the basis that you can design any XML you like and then describe it in XSD. It's designed on the basis that you will design your XML by using the building blocks that XSD provides.

Upvotes: 1

Related Questions