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>
3.139.105.83