How to model `( A | B | C )*` (arbitrary selection of given elements) in RELAX NG?

60 Views Asked by At

Trying to write a RELAX NG schema for a "tag soup" like content model (where there may be a large set of tags), I'm stuck:

Say I have n tags that may appear each optionally in any order. What I tried is this:

<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<!-- ... -->
  <define name="TagSoup">
    <zeroOrMore>
      <element name="A"><text /></element>
      <element name="B"><text /></element>
      <element name="C"><text /></element>
      <!-- ... -->
    </zeroOrMore>
  </define>
</grammar>

But when just a B appears, the input is not accepted. Repeating optional (or zeroOrMore) around every element looks like overkill. Also the ideal solution would not allow elements to repeat in the "tag soup".

1

There are 1 best solutions below

2
mzjn On

Make each element optional and wrap everything in interleave. The following pattern allows each of the A, B, and C elements to occur once or not at all, in any order.

<define name="TagSoup">
  <interleave>
    <optional>
      <element name="A"><text /></element>
    </optional>
    <optional>
      <element name="B"><text /></element>
    </optional>
    <optional>
      <element name="C"><text /></element>
    </optional>
  </interleave>
</define>