Skip to content
Records and dispatch

Records and dispatch

A <Record> connects a kind of data element to the layout code that should handle it. Dispatching data to records is how an XTS layout walks your XML tree: the root element triggers a record, that record processes its children, and so on. This is the data-driven heart of XTS.

Records match data elements

Each <Record> has a match attribute naming the element it handles:

<Record match="catalog">
  <ProcessNode select="*"/>
</Record>

<Record match="article">
  <PlaceObject>
    <TextBlock>
      <Paragraph><Value select="@name"/></Paragraph>
    </TextBlock>
  </PlaceObject>
</Record>

When XTS processes an element, it finds the best-matching record and runs its body. Inside the body, the context is that element, so XPath expressions like @name or description are relative to it.

Records are collected in the setup pass, so their order in the file does not affect which record exists – only the priority rules below decide which one wins when several could match.

ProcessNode – dispatch children to their records

<ProcessNode> sends each selected element to its matching record. Use it when different child elements need different treatment:

<Record match="catalog">
  <ProcessNode select="*"/>
</Record>

<Record match="article"></Record>
<Record match="category-header"></Record>

This is recursive: a record reached via <ProcessNode> can itself call <ProcessNode> to descend further. That recursion is what walks the whole tree.

ProcessNode versus ForAll

There are two ways to iterate over child elements:

  • <ProcessNode> dispatches each child to its matching <Record> – different elements can be handled by different records.
  • <ForAll> runs the same commands for every matched element, right where it is written – ideal for tables and lists. See Control flow.
<!-- ProcessNode: heterogeneous data, one record per element type -->
<Record match="catalog">
  <ProcessNode select="*"/>
</Record>

<!-- ForAll: homogeneous rows, inline -->
<Record match="catalog">
  <PlaceObject>
    <Table stretch="max">
      <ForAll select="article">
        <Tr>
          <Td><Paragraph><Value select="@name"/></Paragraph></Td>
          <Td><Paragraph><Value select="@price"/></Paragraph></Td>
        </Tr>
      </ForAll>
    </Table>
  </PlaceObject>
</Record>

Matching with predicates

The match attribute supports XPath predicates, so you can route the same element to different records based on its attributes or content:

<Record match="item[@type='invoice']"></Record>
<Record match="item[@type='credit']"></Record>
<Record match="item"></Record>   <!-- fallback for any other item -->

Priority

When more than one record could match an element, XTS picks the winner by these rules:

  1. A record with a predicate beats a record without one (more specific wins).
  2. Among records of equal specificity, the last one defined wins.

So in the example above, an <item type="invoice"> is handled by the first record; an <item type="other"> falls through to the plain item record.

Modes

A record can declare a mode, and <ProcessNode> can request one, so the same element can be processed differently in different phases (for instance, once to build a table of contents and once to render the body):

<Record match="chapter" mode="toc"></Record>
<Record match="chapter"></Record>   <!-- default mode -->

<ProcessNode select="chapter" mode="toc"/>
<ProcessNode select="chapter"/>

Only records whose mode matches the <ProcessNode> request are considered.

See also