user2149140
user2149140

Reputation: 143

How can I design an XSD which restricts the usage of elements based on other elements

I am making an XSD file to validate that an IO definition for a system does not contain any "bad" configurations.

In this environment I have a set of different hardware boards, each with a different number of output pins, some of which use additional hardware to extend them.

However, when using certain hardware extensions, certain pins on each board become occupied by the hardware extension and are no longer there for normal use: When we are using an Arduino with a MUX II shield, for instance, pins 17, 18, and 19 are used by the shield.

I want to make my XSD such that the following sequence validates:

...
<ArduinoDuo name="dev1">
    <pin1 name="bLed1" type="output" voltage="5"/>
    ...
    <pin17 name="bSwitchA" type="output" voltage="5"/>
</ArduinoDuo>

as well as

...
<ArduinoDuo name="dev2">
    <pin1 name="bLedXYZ" type="output" voltage="5"/>
    ...
    <pin16 name="bToggleC" type="input" voltage="5"/>
    <MuxII name="LEDExtenderA>
        <pin1 name="bToggleABC" type="input" voltage="25">
    </MuxII>
</ArduinoDuo>

but where the following does NOT validate:

...
<ArduinoDuo name="dev1">
    <pin1 name="bLed1" type="output" voltage="5"/>
    ...
    <pin17 name="bSwitchA" type="output" voltage="5"/>
    <MuxII name="LEDExtenderA>
        <pin1 name="bToggleABC" type="input" voltage="25">
    </MuxII>
</ArduinoDuo>

Ultimately, I would like it so that the use of individual pins is optional, but to restrict their use when the Elements which declare extensions are present.

Upvotes: 0

Views: 45

Answers (2)

Marco Luzzara
Marco Luzzara

Reputation: 6056

This is only a sketch of your XSD Schema:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="pininfo">
        <xs:attribute name="name" type="xs:string"/>
        <xs:attribute name="type" type="xs:string"/>
        <xs:attribute name="voltage" type="xs:string"/>
    </xs:complexType>

    <xs:complexType name="MuxIIinfo">
        <xs:sequence>
            <xs:element name="pin1" type="pininfo"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>

    <xs:complexType name="ArduinoDuoInfo">
        <xs:sequence>
            <xs:element name="pin1" type="pininfo"/>
            <xs:element name="pin16" type="pininfo"/>
            <xs:choice>
                <xs:sequence>
                    <xs:element name="pin17" type="pininfo" maxOccurs="1" minOccurs="0"/>
                    <xs:element name="pin18" type="pininfo" maxOccurs="1" minOccurs="0"/>
                    <xs:element name="pin19" type="pininfo" maxOccurs="1" minOccurs="0"/>
                </xs:sequence>
                <xs:element name="MuxII" type="MuxIIinfo"/>
            </xs:choice>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>

    <xs:element name="ArduinoDuo" type="ArduinoDuoInfo"/>

</xs:schema>

The interesting part is the <xs:choice>, which makes mutual exclusive the sequence pin17, pin18, pin19 with the presence of tag MuxII. Note that I have used minOccurs and maxOccurs to make pinXX tags optional.

Upvotes: 1

Michael Kay
Michael Kay

Reputation: 163675

If it were only this case, you could define a content model

pin1? pin2? ,,,, pin16?, ((pin17?, pin18?, pin19) | MuxII)

using "," for sequence, "?" for optionality, and "|" for choice.

But if there lots of things like MuxII that require certain pins to be absent then this becomes impossible, or at any rate, hopelessly unwieldy.

You need XSD 1.1 with assertions. Then you can write things like

<xs:assert test="not(MuxII) or not(pin17 | pin18 | pin19)"/>

to indicate that either MuxII must be absent, or pins 17, 18, and 19 must be absent.

Upvotes: 1

Related Questions