A template may be used to generate hierarchical trees. This works just like with recursive generation using the content builder. Each level of the tree is created using a successive iteration of the template build process. If the items are containers, the tree builder will mark the right rows as containers, so that they can be opened and closed with the small icon twisties on the left of the column. Remember to make the left column the primary column for these to appear.

To be able to do this, the tree builder must know that an item is a container. Usually you would display a tree from data in an RDF container such as a Seq. In this case, determining that the node is a container is easy. If a node is a RDF container, the tree item becomes a container, and the user may open the row by double-clicking it. Note that this test is done on the member value not the reference value. For instance, in the photo example, we have a container "http://www.xulplanet.com/rdf/myphotos" with three photos. Three results will be generated from a simple rule with no extra conditions. It is the result, or the photo, that will be checked, not the container of photos. Since a photo isn't a container, the tree rows will not become containers, so you will not be able to open them. As the rows are not containers, the tree builder does not recurse to find additional data. The tree builder creates rows lazily, so a closed container will not have any data generated inside in it until the row is opened. When the user opens the tree row, the next level of rows are generated from the template and displayed in the tree. Similarly, when the user closes a tree row, the rows inside it are removed, such that they will have to be generated again the next time the row is opened.

If you want to put rows inside the photo rows, you will either need to make each photo resource an RDF container, or use the containment attribute to specify additional properties that indicate containership. If a particular photo had a value for one of the properties listed in the containment attribute, it would be accepted as a container, and the user could open the row. When the user opens the row, the template will be re-examined for results using the photo as the starting point instead of the top level ref value.

Here is an example for the streets datasource:

<tree id="photosList" flex="1" datasources="template-guide-streets.rdf"
      ref="http://www.xulplanet.com/rdf/myneighbourhood" flags="dont-build-content"
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <treecols>
    <treecol id="address" primary="true" label="Address" flex="1"/>
    <treecol id="floors" label="Floors" flex="1"/>
  </treecols>
  <template>
    <rule rdf:type="http://www.xulplanet.com/rdf/House">
      <treechildren>
        <treeitem uri="rdf:*">
          <treerow>
            <treecell label="rdf:http://www.xulplanet.com/rdf/address"/>
            <treecell label="rdf:http://www.xulplanet.com/rdf/floors"/>
          </treerow>
        </treeitem>
      </treechildren>
    </rule>
    <rule>
      <treechildren>
        <treeitem uri="rdf:*">
          <treerow>
            <treecell label="rdf:http://purl.org/dc/elements/1.1/title"/>
          </treerow>
        </treeitem>
      </treechildren>
    </rule>
  </template>
</tree>

This is similar to a previous example except that it uses a tree. The first rule is for the houses as indicated by the rule's condition and the second rule is for the streets. As shown in the snippet of the data below, the street is a Seq, so it will become a container. The houses are not containers, so they will not have children in the tree.

<rdf:Bag rdf:about="http://www.xulplanet.com/rdf/myneighbourhood">
  <rdf:li>
    <rdf:Seq rdf:about="http://www.xulplanet.com/rdf/marion"
               dc:title="Marion Street">

The result is a two level tree with two columns.