XUL Template Primer - Bindings

  • Revision slug: XUL_Template_Primer_-_Bindings
  • Revision title: XUL Template Primer - Bindings
  • Revision id: 180904
  • Created:
  • Creator: Pd
  • Is current revision? No
  • Comment /* Example */

Revision Content

Overview

This document expands on the {{mediawiki.external('template-primer.html 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 {{mediawiki.external('template-bindings.xul 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> {{mediawiki.external('template-primer.html#conditions 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. {{mediawiki.external('#1 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.

Related Documents

{{mediawiki.external('template-primer.html XUL Template Primer')}}
XUL template basics.
{{mediawiki.external('template-multi.html XUL Template Primer - Multiple Rules')}}
Illustrates how to write templates with multiple <rule> elements.
{{mediawiki.external('template-nested.html XUL Template Primer - Nested Content')}}
Illustrates how a template can be used recursively to build nested content.
{{mediawiki.external('template-outliner.html 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

1As 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.

Revision Source

<h2 name="Overview"> Overview </h2>
<p>This document expands on the {{mediawiki.external('template-primer.html XUL Template Primer')}} by introducing the <code>&lt;bindings&gt;</code> element in the <i>extended XUL template syntax</i>.
</p><p>The <code>&lt;bindings&gt;</code> element is used to create additional, <i>optional</i> variable bindings, in addition to those that are specified in a rule's <code>&lt;conditions&gt;</code>. This is different from the variables specified in the rule's conditions, where a value <i>must</i> be found for each variable for the rule to match. If a <code>&lt;binding&gt;</code> can't be matched, the rule will still fire.
</p>
<h2 name="Example"> Example </h2>
<p>To illustrate how <code>&lt;bindings&gt;</code> work, we'll examine this {{mediawiki.external('template-bindings.xul XUL document')}}, which builds a simple content model an RDF/XML file.
</p>
<pre class="eval"><font color="#999999">&lt;?xml version="1.0"?&gt;

&lt;?xml-stylesheet href="chrome://global/skin" type="text/css"?&gt; 

&lt;window xmlns:html="<span class="plain">http://www.w3.org/1999/xhtml</span>" xmlns="<span class="plain">http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</span>" align="vertical"&gt;</font>

<font color="#000000">&lt;vbox datasources="friends.rdf" ref="urn:root"&gt; 

  &lt;template&gt; 

    &lt;rule&gt; 

      &lt;conditions&gt; 

        &lt;content uri="?uri" /&gt; 

        &lt;triple subject="?uri" 
             predicate="<span class="plain">http://home.netscape.com/NC-rdf#friends</span>" 
                object="?friends" /&gt; 

        &lt;member container="?friends" child="?friend" /&gt; 

        &lt;triple subject="?friend" predicate="<span class="plain">http://home.netscape.com/NC-rdf#name</span>" object="?name" /&gt; 

      &lt;/conditions&gt; 

&lt;bindings&gt; 
&lt;binding subject="?friend" predicate="<span class="plain">http://home.netscape.com/NC-rdf#address</span>" object="?addr" /&gt; 
&lt;binding subject="?addr" predicate="<span class="plain">http://home.netscape.com/NC-rdf#street</span>" object="?street" /&gt; 
&lt;/bindings&gt; 
    &lt;action&gt; 
      &lt;hbox uri="?friend"&gt; 
        &lt;label value="?name" /&gt; 
        &lt;label value="?street" /&gt; 
      &lt;/hbox&gt; 
    &lt;/action&gt; 
  &lt;/rule&gt; 
&lt;/template&gt; 

&lt;/vbox&gt;</font>

<font color="#999999">&lt;/window&gt;</font>
</pre>
<p>The XUL Template Primer covers the <code>&lt;conditions&gt;</code> and <code>&lt;action&gt;</code> elements, so we won't discuss those here.
</p><p>We'll use a the following data model to illustrate how bindings work. See the RDF/XML file <code>friends.rdf</code>, below, a simple database with name and address information for some of my good friends.
</p>
<div class="code">&lt;?xml version="1.0"?&gt; &lt;rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:nc="http://home.netscape.com/NC-rdf#"&gt; &lt;rdf:Description about="urn:root"&gt; &lt;nc:friends&gt; &lt;rdf:Seq&gt; &lt;rdf:li&gt; &lt;rdf:Description nc:name="Alison Appel"&gt; &lt;nc:address resource="#home" /&gt; &lt;/rdf:Description&gt; &lt;/rdf:li&gt; &lt;rdf:li&gt; &lt;rdf:Description nc:name="Jack"&gt; &lt;nc:address resource="#doghouse" /&gt; &lt;/rdf:Description&gt; &lt;/rdf:li&gt; &lt;rdf:li&gt; &lt;rdf:Description nc:name="Lumpy" /&gt; &lt;/rdf:li&gt; &lt;/rdf:Seq&gt; &lt;/nc:friends&gt; &lt;/rdf:Description&gt; &lt;rdf:Description ID="home" nc:street="437 Hoffman" /&gt; &lt;rdf:Description ID="doghouse" nc:street="435 Hoffman" /&gt; &lt;/rdf:RDF&gt;</div>
<p>The RDF model that this file creates can be represented with the following graph.
</p><p><img alt="RDF Data Model" src="File:en/Media_Gallery/Friends-rdf-model.gif">
</p><p>When displayed in Mozilla, something like this appears:
</p><p><img alt="Screenshot" src="File:en/Media_Gallery/Template-bindings-screenshot.gif">
</p><p>Note that even though poor Lumpy has no <code><i>nc</i><span class="plain">:address</span></code> property, he still appears in the content model! Unlike the <code>&lt;conditions&gt;</code>, bindings do not affect whether or not a rule matches: they just "pull through" additional information if it is available.
</p>
<h2 name="The_.3Cbindings.3E_element"> The &lt;bindings&gt; element </h2>
<p>The <code>&lt;bindings&gt;</code> element is optional in a XUL template, but if present, must appear as a sibling of the <code>&lt;conditions&gt;</code> and <code>&lt;action&gt;</code> elements in a rule.
</p>
<h2 name="The_.3Cbinding.3E_element"> The &lt;binding&gt; element </h2>
<p>The <code>&lt;bindings&gt;</code> element (plural) may contain any number of <code>&lt;binding&gt;</code> (singular) elements.
</p>
<div class="code">&lt;bindings&gt; &lt;binding subject="?friend" predicate="http://home.netscape.com/NC-rdf#address" object="?addr" /&gt; &lt;binding subject="?addr" predicate="http://home.netscape.com/NC-rdf#street" object="?street" /&gt; &lt;/bindings&gt;</div>
<p>The <code>&lt;binding&gt;</code> element is very much like the <code>&lt;triple&gt;</code> {{mediawiki.external('template-primer.html#conditions condition')}}<span class="plain">: it must have a </span><code>subject</code>, <code>predicate</code>, and <code>object</code> attribute. These refer to the subject, predicate, and object of a statement in the RDF model.
</p><p>At least one of the <code>&lt;binding&gt;</code> elements must have a <code>subject</code> variable that appears in the <code>&lt;conditions&gt;</code><span class="plain">: this variable is the "hook" that is used to bootstrap the binding. In our example, the </span><code>?friend</code> variable serves this purpose in the first <code>&lt;binding&gt;</code> element.
</p><p>The subject may refer to any variable that has been computed in the <code>&lt;conditions&gt;</code>, or it may refer to another <code>&lt;binding&gt;</code>'s <code>object</code> variable. <sup>{{mediawiki.external('#1 1')}}</sup> In our example, the second <code>&lt;binding&gt;</code>'s <code>subject</code> does this: the value for the <code>?addr</code> variable is computed by the first <code>&lt;binding&gt;</code>
</p><p>The <code>predicate</code> must name the URI of an RDF property, in this case, <code><i>nc</i><span class="plain">:address</span></code>.
</p><p>The <code>object</code> must name a variable. The value of the <code>object</code>'s variable will be computed by invoking the <code>GetTarget()</code> method using the <code>object</code>'s value as the <code>aSource</code> argument, and the <code>predicate</code>'s resource as the <code>aProperty</code> argument. (See the <a class="external" href="http://lxr.mozilla.org/mozilla/source/rdf/base/idl/nsIRDFDataSource.idl"><code>nsIRDFDataSource</code></a> interface for more details.)
</p><p>In our example, the <code>&lt;rule&gt;</code> will be instantiated <i>three times</i><span class="plain">: once each for Alison, Jack, and Lumpy. However, in Lumpy's case, we won't be able to bind the </span><code>?addr</code> variable because Lumpy has no home! (Well, there are no statements with Lumpy as the subject and a <code><i>nc</i><span class="plain">:address</span></code> as the predicate, anyway.) Nevertheless, <i>the rule still matches</i>.
</p><p>In the content that's built for Lumpy's <code>&lt;hbox&gt;</code>, the second <code>&lt;label&gt;</code>'s <code>value</code> attribute (which should contain the value of <code>?street</code>) is just left blank.
</p>
<h2 name="Related_Documents"> Related Documents </h2>
<dl><dt> {{mediawiki.external('template-primer.html XUL Template Primer')}}
</dt><dd> XUL template basics.
</dd><dt> {{mediawiki.external('template-multi.html XUL Template Primer - Multiple Rules')}}
</dt><dd> Illustrates how to write templates with multiple <code>&lt;rule&gt;</code> elements.
</dd><dt> {{mediawiki.external('template-nested.html XUL Template Primer - Nested Content')}}
</dt><dd> Illustrates how a template can be used recursively to build <i>nested content</i>.
</dd><dt> {{mediawiki.external('template-outliner.html XUL Template Primer - Outliner')}}
</dt><dd> Illustrates how a template can be used as a view for a XUL outliner.
</dd><dt> <a class="external" href="http://www.mozilla.org/rdf/doc/xul-template-reference.html">XUL Template Reference</a>
</dt><dd> Describes the <i>simple XUL template syntax</i> in detail.
</dd></dl>
<h2 name="Notes"> Notes </h2>
<p><sup>1</sup>As of this writing, it is necessary to order <code>&lt;binding&gt;</code> elements carefully. Specifically, if a binding depends on a variable in another binding, it must appear <i>after</i> the binding it depends on. For example, the sample in this document wouldn't work if the two <code>&lt;binding&gt;</code> elements were reversed, because of the dependency on the <code>?addr</code> variable. Fortunately, this is the natural way one would write bindings, so in practice this should not be a burden.
</p>
Revert to this revision