RELAX NG by Eric van der Vlist will be published by O'Reilly & Associates (ISBN: 0596004214)

You are welcome to use our annotation system to give your feedback.


Why is it called "interleave" instead of "unorderedGroup"?

If interleave were only about defining unordered groups why would it be called interleave and not "unorderedGroup" or something similar? interleave has hidden sophistication. It is not only a definition for unordered groups; it's also a definition for unordered groups that let their child nodes intermix within subgroups. Mixing is allowed even when these groups are ordered groups. I promise, this concept is simpler than it looks in this semi-formal definition. An example will make it easier to grasp.

That ordered groups can be immersed in an unordered group may be surprising. We can try a real world metaphor to illustrate it. If we imagine that the elements of a XML document are like a bunch of tourists visiting a museum, we can define the unordered sets as all the tourists visiting. The ordered groups of tourists, who are within the unordered set, are following guides. There are many different ways to immerse ordered groups within the unordered set of museum visitors and to mix ordered groups together. The interleave pattern describes one specific way to effect this immersion: when the museum is an interleave pattern, the ordered groups preserve only the relative order of their members. This not only allows individual tourists to insert themselves within a group but also lets two groups to "interleave" their members.

To return to XML and RELAX NG, let's examine the following schema:

 <element xmlns="http://relaxng.org/ns/structure/1.0" name="museum">
  <interleave>
   <element name="individual"><empty/></element>
   <group>
    <element name="group-member1"><empty/></element>
    <element name="group-member2"><empty/></element>
   </group>
  </interleave>
 </element>

or, using the compact syntax:

 element museum {
  element individual {empty} &
  (
   element group-member1 {empty},
   element group-member2 {empty}
  )
 }

An individual represents an individual visiting the museum while elements group-member1 and group-member2 represent visitors in a group. Because interleave patterns are not ordered groups, the following instance documents are valid:

 <museum>
  <individual/>
  <group-member1/>
  <group-member2/>
 </museum>

and

 <museum>
  <group-member1/>
  <group-member2/>
  <individual/>
 </museum>

These documents are instances where the element individual, which matches the first pattern in the interleave pattern (i.e. the element pattern), is either before or after the elements group-member1 and group-member2 which match the group pattern - the second sub-pattern of the interleave pattern. Because the interleave pattern allows that the nodes matching its sub-pattern are mixed, the schema will also validate this third combination:

 <museum>
  <group-member1/>
  <individual/>
  <group-member2/>
 </museum>

On the other hand, because of the way we ordered the elements in the group declaration of the schema, all the combinations where the relative order between group members would not be respected would be invalid. A example of such an invalid combination is:

 <museum>
  <group-member2/>
  <individual/>
  <group-member1/>
 </museum>

Interleave can also be used to mix two groups of patterns. In this case the relative order of the element of each group is maintained but the elements of different groups may appear in any order and the groups may be "interleaved". For an example, let's look at the following schema:

 <element xmlns="http://relaxng.org/ns/structure/1.0" name="museum">
  <interleave>
   <group>
    <element name="group1.member1"><empty/></element>
    <element name="group1.member2"><empty/></element>
   </group>
   <group>
    <element name="group2.member1"><empty/></element>
    <element name="group2.member2"><empty/></element>
   </group>
  </interleave>
 </element>

or, using the compact syntax:

 element museum{
  (
   element group1.member1 {empty},
   element group1.member2 {empty}
  ) & (
   element group2.member1 {empty},
   element group2.member2 {empty}
  )
 }

will validate documents such as:

 <museum>
  <group1.member1/>
  <group1.member2/>
  <group2.member1/>
  <group2.member2/>
 </museum>

and

 <museum>
  <group2.member1/>
  <group2.member2/>
  <group1.member1/>
  <group1.member2/>
 </museum>

where the groups are kept separated but also:

 <museum>
  <group1.member1/>
  <group2.member1/>
  <group2.member2/>
  <group1.member2/>
 </museum>

or

 <museum>
  <group1.member1/>
  <group2.member1/>
  <group1.member2/>
  <group2.member2/>
 </museum>

where the groups are interleaved.


You are welcome to use our annotation system to give your feedback.
[Annotations for this page]
All text is copyright Eric van der Vlist, Dyomedea. During development, I give permission for non-commercial copying for educational and review purposes. After publication, all text will be released under the Free Software Foundation GFDL.