Search code examples
pythonxmllxmlrelaxng

RelaxNG: Having more than one of a similar element in <interleave>


The requirement is as such:

  • A feed will have multiple links
  • A "B" type link MUST appear atleast once
  • An "A" type link MAY appear zero or more times
  • "A" type links can appear in other places too hence need to keep the define independent

I get the following error with the code
lxml.etree.RelaxNGParseError: Element or text conflicts in interleave, line 6

Example code below

from io import StringIO
from lxml import etree

XML = StringIO('''
<root xmlns="http://www.w3.org/2005/Atom">
    <link rel="a1" />
    <link rel="b1" />
    <link rel="a2" />
    <link rel="b2" />
</root>
''')

RNG = StringIO('''
<grammar xmlns="http://relaxng.org/ns/structure/1.0">

    <start>
        <element name="root" ns="http://www.w3.org/2005/Atom">
            <interleave>
                <zeroOrMore>
                    <ref name="aLink"/>
                </zeroOrMore>
                <oneOrMore>
                    <ref name="bLink"/>
                </oneOrMore>
            </interleave>
        </element>
    </start>

    <define name="aLink" ns="http://www.w3.org/2005/Atom">
        <element name="link">
            <choice>
                <attribute name="rel">
                    <value>a1</value>
                </attribute>
                <attribute name="rel">
                    <value>a2</value>
                </attribute>
            </choice>
        </element>
    </define>

    <define name="bLink" ns="http://www.w3.org/2005/Atom">
        <element name="link">
            <choice>
                <attribute name="rel">
                    <value>b1</value>
                </attribute>
                <attribute name="rel">
                    <value>b2</value>
                </attribute>
            </choice>
        </element>
    </define>

</grammar>
''')

rng_tree = etree.parse(RNG)
rng_schema = etree.RelaxNG(rng_tree)

rng_schema.validate(XML)

Solution

  • I fear that it's a typical case that is forbidden by the specification of Relax NG

    7.4. Restrictions on interleave

    For a pattern p1 p2 ,

    • there must not be a name that belongs to both the name class of an element pattern referenced by a ref pattern occurring in p1 and the name class of an element pattern referenced by a ref pattern occurring in p2, and a text pattern must not occur in both p1 and p2.

    https://www.oasis-open.org/committees/relax-ng/spec-20011203.html#interleave-restrictions