Recursive Generation

In the previous example, the template builder generated an extra set of two buttons for the second row. However, the labels on the second set of buttons are different than the first set. If you look at the graph again, you might begin to see why. In the graph, item C has a relatedItem arrow pointing out of it to item D. This extra arrow which neither B or D have causes an extra set of buttons to be created.

After generating content, the template builder always repeats the generation for inner levels as far as it can go. Thus, the builder can be said to generate content from the graph recursively. After generating a result's content, the builder starts again using a new parent and starting point. Naturally, the parent will be the new result's content, rather than the outer containing element, and the starting point will be the endpoint of the previous iteration. For the top level generation the parent insertion point is the element with the datasources attribute, in this example a <vbox>. For nested results, the insertion point is the generated element. Here is the content that was generated after one iteration:

<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
      ref="http://www.xulplanet.com/rdf/A">
  <template>
    <query>
      <content uri="?start"/>
      <triple subject="?start"
              predicate="http://www.xulplanet.com/rdf/relatedItem"
              object="?relateditem"/>
    </query>
    <action>
      <hbox uri="?relateditem">
        <button label="?start"/>
        <button label="?relateditem"/>
      </hbox>
    </action>
  </template>
  <hbox id="http://www.xulplanet.com/rdf/B">
    <button label="http://www.xulplanet.com/rdf/A"/>
    <button label="http://www.xulplanet.com/rdf/B"/>
  </hbox>
  <hbox id="http://www.xulplanet.com/rdf/C">
    <button label="http://www.xulplanet.com/rdf/A"/>
    <button label="http://www.xulplanet.com/rdf/C"/>
  </hbox>
  <hbox id="http://www.xulplanet.com/rdf/D">
    <button label="http://www.xulplanet.com/rdf/A"/>
    <button label="http://www.xulplanet.com/rdf/D"/>
  </hbox>
</vbox>

For the next iteration, the insertion point will be the three <hbox> elements. However, since C is the only element that will end up having any additional content, only the second <hbox> element will have additional children added to it.

For a nested item, the builder processes the query in the same way as usual, however instead of using the ref attribute as the seed starting point, the end point or member is used instead. This will correspond to the id on the appropriate element in the generated content above. To begin, B is evaluated and seeded with the right value:

(?start = http://www.xulplanet.com/rdf/B)

The <triple> statement is then examined, however, item B doesn't have a relatedItem arc out of it, so the result is rejected. Since there are no potential results, the builder doesn't generate anything. A similar situation will occur for item D. However, for item C, the triple does match an item, so the data will be added to the potential result:

(?start = http://www.xulplanet.com/rdf/C, ?relateditem = http://www.xulplanet.com/rdf/D)

Image:Template-guide-p9.png

A match has occured, so the content within the action body will be created and added inside item C. Since the ?start variable points to item C and the ?relateditem variable points to D, the buttons will be created with these labels. If you look at the image of the example again, you will see that the buttons do have these labels. The resulting content for row C will look like this:

<hbox id="http://www.xulplanet.com/rdf/C">
  <button label="http://www.xulplanet.com/rdf/A"/>
  <button label="http://www.xulplanet.com/rdf/C"/>
  <hbox id="http://www.xulplanet.com/rdf/D">
    <button label="http://www.xulplanet.com/rdf/C"/>
    <button label="http://www.xulplanet.com/rdf/D"/>
  </hbox>
</hbox>

The recursive nature of templates has useful applications in menus and trees so that sets of iterative content can be generated automatically. We'll look more at recursive templates later, but next, let's look at a more practical example.