2

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?

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256

1 Answers1

5

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

Brett Kail
  • 33,593
  • 2
  • 85
  • 90
  • 1
    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 May 10 '10 at 22:49
  • Can you link me to some documentation somewhere which confirms this? – Eli Courtwright May 10 '10 at 22:51
  • @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 May 10 '10 at 22:53
  • @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 May 10 '10 at 23:09
  • 1
    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 – Brett Kail May 10 '10 at 23:09
  • Updated xml-dev link: http://lists.xml.org/archives/xml-dev/200503/msg00109.html – Brett Kail Mar 08 '21 at 14:37