Node:Step 6, Next:, Previous:Step 5, Up:Tutorial



Step 6: More annotations

The ancestors annotation searches each of the parent directories of the currently processed file. It is useful for creating a 'you-are-here' or 'breadcrumbs' style navigation links. Unlike other annotations, the ordering does not depend on the file or directory name - the order is the directory hierarchy from top to bottom. The first file in the annotation will always be the one for the root of the source tree. The last file will be the one for the directory containing the currently processed file. If the currently processed file happens to also match the file-name, it will also appear in the annotation.

The members annotation picks up other files in the current directory. However, we won't be using it in this tutorial. (A hint to remember: all these annotations have names which are plurals - e.g. "members", not "member".)

Design the layout of the source tree directories with annotations in mind so that they can be used to generate the site navigation links. The children annotation picks up files in immediate subdirectories. The ancestors annotation picks up files in the parent directories. The members annotation picks up files in the current directory.

If a directory doesn't have a file with a matching name, that directory is just skipped. That might be useful if you want to have a directory that is not reflected in the Web site's navigation hierarchy.

So far, annotations have been calculated relative to the directory containing the currently processed source file - that can be changed using the dir annotation. It has a mandatory path attribute which specifies the new working directory. This path can be relative or absolute, and may optionally be prefixed by transbuild:// as a reminder that it is in the source tree file space.

Annotations listed inside the dir element are processed relative to that new directory. In the output, a dir element is created and the annotations in the dir are nested inside it.

You can add multiple annotations in one xml-load. The annotation elements will be appended in the same order as supplied. For example, we'll change the rule to:

<rule source-suffix=".xml" target-suffix=".html">
  <xml-load>
    <dir path="/">
      <children file-name="index.xml"/>
    </dir>
    <ancestors file-name="index.xml"/>
    <children file-name="index.xml"/>
  </xml-load>
  <xslt stylesheet="scripts/tr06.xsl"/>
</rule>

This will parse the source file and annotate it to create a large body of XML data containing something like:

<article
 xmlns:TBA="http://hoylen.com/ns/xmlns/2002/transbuild/annotation"
 TBA:source="transbuild://hardware/index.xml">

  <title>Hardware</title>
  <para>Our products incorporate leading edge technology with award
  winning design which is both beautiful and functional.</para>

  <TBA:dir TBA:source="transbuild://">
    <TBA:children>
      <article
       TBA:source="transbuild://about/index.xml">...</article>
      <article
       TBA:source="transbuild://contact/index.xml">...</article>
      <article
       TBA:source="transbuild://hardware/index.xml">...</article>
      <article
       TBA:source="transbuild://software/index.xml">...</article>
    </TBA:children>
  </TBA:dir>

  <TBA:ancestors>
    <article TBA:source="transbuild://index.xml">...</article>
    <article TBA:source="transbuild://hardware/index.xml">...</article>
  </TBA:ancestors>

  <TBA:children>
    <article
     TBA:source="transbuild://hardware/mp100/index.xml">...</article>
    <article
     TBA:source="transbuild://hardware/mp120/index.xml">...</article>
    <article
     TBA:source="transbuild://hardware/mp110/index.xml">...</article>
    <article
     TBA:source="transbuild://hardware/mp130/index.xml">...</article>
    <article
     TBA:source="transbuild://hardware/omp/index.xml">...</article>
  </TBA:children>

</article>

Notice that the ordering of the imported root elements is sorted in lexicographical order, except for the ancestors annotation. In this example, the data from the ~source~/hardware/index.xml file appears three times (as the document itself, in the children of the directory annotation, and in the last ancestors annotation). This may seem very inefficient, but don't worry about it - most of the time your files are small and Transbuild creates these annotations very efficiently by caching the parsed XML data.

The XSLT script is modified to use the information from the annotations. The top level children are used to create navigation links into the different major sections of the site. The ancestor annotations will be used to create a "bread-crumbs" navigation showing all the levels above the current page.

<xsl:template match="article">
  <body>
    <div class="nav-top">
      <ul>
        <li><a href="{TBF:href('/index.xml')}">Home</a></li>
        <xsl:for-each select="/article/TBA:dir/TBA:children/article">
          <xsl:sort select="@status" data-type="number"
                    order="ascending"/>
          <li>
            <a href="{TBF:href(@TBA:source)}">
              <xsl:value-of select="title"/>
            </a>
          </li>
        </xsl:for-each>
      </ul>
    </div>

    <h1><xsl:value-of select="title"/></h1>

    <div class="nav-hier">
      <xsl:for-each select="/article/TBA:ancestors/article">
        <xsl:if test="position() != 1">
          <xsl:text> &gt; </xsl:text>
        </xsl:if>
        <a href="{TBF:href(@TBA:source)}">
          <xsl:value-of select="title"/>
        </a>
      </xsl:for-each>
      <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
    </div>

    ...

This step can be tested by running Transbuild on the build script file tb-step06.xml. It produces a set of Web pages with a set of navigation links.

The usefulness of Transbuild is now apparent. By using Transbuild annotations, the navigation links are all generated automatically without any hand editing of the source files. By carefully writing flexible XSLT scripts, you can future-proof your site. For example, if we wanted to add a new section to the site (e.g. for support), all you have to do is create a directory ~source~/support and a single file ~source~/support/index.xml and re-run Transbuild. A new set of Web pages will be generated, with every page having a top level link to that new section. It's that simple - try it! Or, try adding a new hardware product by creating a single directory and one file.