XUL Template Primer - Bindings

Warning: The content of this article may be out of date. See XUL:Template Guide for up to date documentation.

Overview

This document expands on the XUL Template Primer by introducing the <bindings> element in the extended XUL template syntax.

The <bindings> element is used to create additional,optional variable bindings, in addition to those that are specified in a rule's <conditions>. This is different from the variables specified in the rule's conditions, where a value must be found for each variable for the rule to match. If a <binding> can't be matched, the rule will still fire.

Example

To illustrate how <bindings> work, we'll examine this XUL document, which builds a simple content model an RDF/XML file.

<?xml version="1.0"?>

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>

<window xmlns:html="http://www.w3.org/1999/xhtml" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="vertical">
  <vbox datasources="friends.rdf" ref="urn:root">
    <template>
      <rule>
        <conditions>
          <content uri="?uri"/>
          <triple subject="?uri"
                predicate="http://home.netscape.com/NC-rdf#friends"
                   object="?friends"/>
          <member container="?friends" child="?friend"/>
          <triple subject="?friend"
                predicate="http://home.netscape.com/NC-rdf#name"
                   object="?name"/>
        </conditions>
        <bindings>
          <binding subject="?friend"
                 predicate="http://home.netscape.com/NC-rdf#address"
                    object="?addr"/>
          <binding subject="?addr"
                 predicate="http://home.netscape.com/NC-rdf#street"
                    object="?street"/>
        </bindings>
        <action>
          <hbox uri="?friend">
            <label value="?name"/>
            <label value="?street"/>
          </hbox>
        </action>
      </rule>
    </template>
  </vbox>
</window>

The XUL Template Primer covers the <conditions> and <action> elements, so we won't discuss those here.

We'll use a the following data model to illustrate how bindings work. See the RDF/XML file friends.rdf, below, a simple database with name and address information for some of my good friends.

<?xml version="1.0"?>

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:nc="http://home.netscape.com/NC-rdf#">
  <rdf:Description about="urn:root">
    <nc:friends>
      <rdf:Seq>
        <rdf:li>
          <rdf:Description nc:name="Alison Appel">
            <nc:address resource="#home"/>
          </rdf:Description>
        </rdf:li>
        <rdf:li>
          <rdf:Description nc:name="Jack">
            <nc:address resource="#doghouse"/>
          </rdf:Description>
        </rdf:li>
        <rdf:li>
          <rdf:Description nc:name="Lumpy"/>
        </rdf:li>
      </rdf:Seq>
    </nc:friends>
  </rdf:Description>
  <rdf:Description ID="home" nc:street="437 Hoffman"/>
  <rdf:Description ID="doghouse" nc:street="435 Hoffman"/>
</rdf:RDF>


The RDF model that this file creates can be represented with the following graph.

RDF Data Model

When displayed in Mozilla, something like this appears:

Screenshot

Note that even though poor Lumpy has no nc:address property, he still appears in the content model! Unlike the <conditions>, bindings do not affect whether or not a rule matches: they just "pull through" additional information if it is available.

The <bindings> element

The <bindings> element is optional in a XUL template, but if present, must appear as a sibling of the <conditions> and <action> elements in a rule.

The <binding> element

The <bindings> element (plural) may contain any number of <binding> (singular) elements.

<bindings>
  <binding subject="?friend"
         predicate="http://home.netscape.com/NC-rdf#address"
            object="?addr"/>
  <binding subject="?addr"
         predicate="http://home.netscape.com/NC-rdf#street"
            object="?street"/>
</bindings>

The <binding> element is very much like the <triple> condition: it must have a subject, predicate, and object attribute. These refer to the subject, predicate, and object of a statement in the RDF model.

At least one of the <binding> elements must have a subject variable that appears in the <conditions>: this variable is the "hook" that is used to bootstrap the binding. In our example, the ?friend variable serves this purpose in the first <binding> element.

The subject may refer to any variable that has been computed in the <conditions>, or it may refer to another <binding>'s object variable.[1] In our example, the second <binding>'s subject does this: the value for the ?addr variable is computed by the first <binding>

The predicate must name the URI of an RDF property, in this case, nc:address.

The object must name a variable. The value of the object's variable will be computed by invoking the GetTarget() method using the object's value as the aSource argument, and the predicate's resource as the aProperty argument. (See the nsIRDFDataSource interface for more details.)

In our example, the <rule> will be instantiated three times: once each for Alison, Jack, and Lumpy. However, in Lumpy's case, we won't be able to bind the ?addr variable because Lumpy has no home! (Well, there are no statements with Lumpy as the subject and a nc:address as the predicate, anyway.) Nevertheless, the rule still matches.

In the content that's built for Lumpy's <hbox>, the second <label>'s value attribute (which should contain the value of ?street) is just left blank.

XUL Template Primer
XUL template basics.
XUL Template Primer - Multiple Rules
Illustrates how to write templates with multiple <rule> elements.
XUL Template Primer - Nested Content
Illustrates how a template can be used recursively to build nested content.
XUL Template Primer - Outliner
Illustrates how a template can be used as a view for a XUL outliner.
XUL Template Reference
Describes the simple XUL template syntax in detail.

Notes

1. As of this writing, it is necessary to order <binding> elements carefully. Specifically, if a binding depends on a variable in another binding, it must appear after the binding it depends on. For example, the sample in this document wouldn't work if the two <binding> elements were reversed, because of the dependency on the ?addr variable. Fortunately, this is the natural way one would write bindings, so in practice this should not be a burden.

Original Document Information

  • Author: Chris Waterson