XML schema; multiple from a list of valid attribute values

Dan Lugg picture Dan Lugg · Dec 31, 2011 · Viewed 19.5k times · Source

I'm reasonably new to working with XML schemas, so excuse my incompetence if this is more trivial than I myself believe it must be.

I'm trying to create a required attribute that must contain 1 or more white-space-separated string values from a list. The list is the 4 typical HTTP request methods; get, post, put, and delete.

So valid elements would include:

<rule methods="get" />
<rule methods="get post" />
<rule methods="post put delete" />

Whereas invalid elements would include:

<rule methods="get get" />
<rule methods="foobar post" />
<rule methods="get;post;put" />

I've tried fooling with enumerations and length, but I don't believe I'm understanding what I need to do (or for that matter if it is in fact possible, though it seems as though it should be)


This is where I'm at now, thanks to @tdrury:

<xs:attribute name="methods" use="required">
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:whiteSpace value="collapse" />
            <xs:pattern value="(?:(?:get|post|put|delete)\s?){1,4}" />
        </xs:restriction>
    </xs:simpleType>
</xs:attribute>

Which works, except for repetition (such as get get or post post post) and absent whitespace (such as getpost or postputdelete)


Edit:

After playing around with this a bit, I came up with an idea: an enumeration of all possible sequences. Thankfully, this list is (for the time being) fixed to the four usual transport methods, get, post, put, and delete, so I figured:

<xs:restriction base="xs:string">
    <xs:whiteSpace value="collapse" />
    <xs:enumeration value="delete" />
    <xs:enumeration value="put" />
    <xs:enumeration value="put delete" />
    <xs:enumeration value="post" />
    <xs:enumeration value="post delete" />
    <xs:enumeration value="post put" />
    <xs:enumeration value="post put delete" />
    <xs:enumeration value="get" />
    <xs:enumeration value="get delete" />
    <xs:enumeration value="get put" />
    <xs:enumeration value="get put delete" />
    <xs:enumeration value="get post" />
    <xs:enumeration value="get post delete" />
    <xs:enumeration value="get post put" />
    <xs:enumeration value="get post put delete" />
</xs:restriction>

Can anyone see a reason that this would not be a good idea?

Answer

DRH picture DRH · Jan 1, 2012

The basic problem can be addressed with enumerations as well:

<xs:attribute name="methods" use="required">
    <xs:simpleType>
        <xs:restriction>
            <xs:simpleType>
                <xs:list>
                    <xs:simpleType>
                        <xs:restriction base="xs:token">
                            <xs:enumeration value="get"/>
                            <xs:enumeration value="post"/>
                            <xs:enumeration value="put"/>
                            <xs:enumeration value="delete"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:list>
            </xs:simpleType>
            <xs:minLength value="1"/>
        </xs:restriction>
    </xs:simpleType>
</xs:attribute>

This unfortunately has the same limitation as the <xs:pattern> solution and cannot validate that each token in the list is unique. It does however address the whitespace issue (getpost would be rejected).