views:

60

answers:

1

I'm working with an XML document where a tag must either have one set of attributes or another. For example, it needs to either look like <tag foo="hello" bar="kitty" /> or <tag spam="goodbye" eggs="world" /> e.g.

<root>
    <tag foo="hello" bar="kitty" />
    <tag spam="goodbye" eggs="world" />
</root>

So I have an XSD schema where I use the xs:choice element to choose between two different attribute groups:

<xsi:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified">
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="tag">
                    <xs:choice>
                        <xs:complexType>
                            <xs:attribute name="foo" type="xs:string" use="required" />
                            <xs:attribute name="bar" type="xs:string" use="required" />
                        </xs:complexType>
                        <xs:complexType>
                            <xs:attribute name="spam" type="xs:string" use="required" />
                            <xs:attribute name="eggs" type="xs:string" use="required" />
                        </xs:complexType>
                    </xs:choice>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xsi:schema>

However, when using lxml to attempt to load this schema, I get the following error:

>>> from lxml import etree  
>>> etree.XMLSchema( etree.parse("schema_choice.xsd") )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "xmlschema.pxi", line 85, in lxml.etree.XMLSchema.__init__ (src/lxml/lxml.etree.c:118685)
lxml.etree.XMLSchemaParseError: Element '{http://www.w3.org/2001/XMLSchema}element': The content is not valid. Expected is (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))., line 7

Since the error is with the placement of my xs:choice element, I've tried putting it in different places, but no matter what I try, I can't seem to use it to define a tag to have either one set of attributes (foo and bar) or another (spam and eggs).

Is this even possible? And if so, then what is the correct syntax?

+2  A: 

It is unfortunately not possible to use choice with attributes in XML schema. You will need to implement this validation at a higher level.

bkail
Indeed. I strongly suggest using RELAX NG for any kind of XML validation, unless you need it for something else that mandates XML Schema (XSLT, XQuery, WS-* etc). In fact, lxml can handle RELAX NG in Python - see http://stackoverflow.com/questions/1254919/how-do-i-validate-xml-document-via-relax-ng-schema-in-python
Pavel Minaev
@bkail: Can you link me to some documentation somewhere which confirms this?
Eli Courtwright
@Pavel: Thanks for the tip, I'll definitely consider that when writing my own schemas in the future; unfortunately at the moment I'm simply debugging an invalid schema written by someone at another company, so I'm stuck with XSD.
Eli Courtwright
@Eli: the official spec doesn't state so explicitly, it's implicit in the definition of various constructs. That said, a simple google search: http://www.google.com/search?q=xml+schema+attribute+choice - will give you plenty of references for this question being asked in many places, including the official XML mailing list, with the same answer everywhere.
Pavel Minaev
I don't think you'll find the absence of function in a spec. The best I can do is link to an email from Michael Kay, a widely regarded expert on XML technologies:http://www.stylusstudio.com/xmldev/200503/post90100.html
bkail