by Eric van der Vlist is published by O'Reilly & Associates (ISBN: 0596004214)


Why Is It Called interleave?

If interleave were only about defining unordered groups, why would it be called interleave and not unorderedGroup or something similar? The interleave pattern has hidden sophistication. It isn't 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 semiformal definition. An example will make it easier to grasp.

That ordered groups can be immersed in an unordered group might be surprising. Let's try a real-world metaphor to illustrate it. Imagine that the elements of a XML document are like a bunch of tourists visiting a museum; you can then 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 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 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 in which 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 subpattern of the interleave pattern. Because the interleave pattern allows that the nodes matching its subpattern to be mixed, the schema also validates this third combination:

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

On the other hand, because of how the elements are ordered in the group declaration of the schema, all the combinations in which the relative order between group members aren't respected are invalid. Here's an example of such an invalid combination:

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

The interleave pattern 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}
  )
 }

This schema validates 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>

in which the groups are interleaved.


This text is released under the Free Software Foundation GFDL.