Neil's Place

June 30, 2005

8:06 PM How Templates Work XVII - Generating a Filter Menu

Templates may be used to generate any type of content. It is common to use a template to generate the items on a menu or in a listbox or tree. The syntax is the same regardless of what type of content is being created. In the previous example, we hard-coded a menulist with the list of countries, but we could also generate this list from the datasource. The same datasource may used for both the photos list and the menulist. Even though the same datasource is used, it will only be loaded once and both templates will be notified when the data has loaded.

We will need to add some information to the datasource in order to specify the list of countries that are available. There are two possibilities. First, a separate Seq could be added listing the countries. Then, a simple <member> condition can be used to iterate over it. Or, we could use an RDF type to specify the countries. Then, we could just look for all resources that were of the 'Country' type. We'll use this method here since we've already seen examples of generating results from a container.

An RDF type can be assigned to a node by using the predicate 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' set to a resource for that type. In RDF/XML, a syntax shortcut may be used which involves replacing the Description tag with the type. We need to add the type to the two countries in the datasource, as well as ensure that the namespace is declared on the root RDF tag:

<nso:Country about="http://www.daml.org/2001/09/countries/iso#IT"
             dc:title="Italy"/>
<nso:Country about="http://www.daml.org/2001/09/countries/iso#NL"
             dc:title="Netherlands"/>

The type of these two resources, when expanded with the namespace (not shown here), will be 'http://www.daml.org/2001/09/countries/country-ont#Country'. The resulting RDF triples for the first country will be:

http://www.daml.org/2001/09/countries/iso#IT
  -> http://www.w3.org/1999/02/22-rdf-syntax-ns#type
  -> http://www.daml.org/2001/09/countries/country-ont#Country
http://www.daml.org/2001/09/countries/iso#IT
  -> http://purl.org/dc/elements/1.1/title
  -> Italy
The type is just like any other triple in the datasource, so we don't need any special syntax to navigate over it. We just need to use the right predicate to look for all the countries. You might wonder what the ref attribute or starting point should be set to since there is no container for the countries. Actually, we can just use the type as the starting point.

<menulist datasources="template-guide-photos4.rdf"
          ref="http://www.daml.org/2001/09/countries/country-ont#Country">

Remember that the only requirement is that the starting point be a resource, but it doesn't matter what resource is used. The conditions will need to iterate over the arcs pointing into the type resource. Since we want the arcs pointing into the type, we need to determine the source or subject of a triple. Look at the resulting RDF triples above again if this is unclear. The starting node is 'http://www.daml.org/2001/09/countries/country-ont#Country'. We need to iterate over the 'type' predicate to find the individual countries. A second triple is used to get the title for the country.

<conditions>
  <content uri="?start"/>
  <triple subject="?country"
          predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
          object="?start"/>
  <triple subject="?country"
          predicate="http://purl.org/dc/elements/1.1/title"
          object="?countrytitle"/>
</conditions>

The action body will need to generate a <menuitem> for each result. It will also need to include a <menupopup> around all of the items. Since we only want to generate a single menupopup, it should go outside of the element with the uri attribute. Only the contents at the element with the uri attribute and below are copied for each result. The elements above are not.

<action>
  <menupopup>
    <menuitem uri="?country" label="?countrytitle" value="?country"/>
  </menupopup>
</action>

The result will be two generated menuitems, one for each country, inside a menupopup. The value attribute is assigned the ?country variable so that the applyFilter function can use this value easily for filtering. The complete example shows this working. Note that due to a bug with template generation in menulists when the datasource hasn't loaded yet, you may have to load the example twice to get it work. This issue only affects the menulist element. Several workarounds can be used in this simple example. First, you could move the <menupopup> element outside of the template and put the datasources attribute on it instead of the <menulist> element. This will work in this simple example, but has the disadvantage that the builder won't be able to generate the content lazily only when the popup is opened. Another workaround is to just rebuild the template once the data has been loaded.

Next, we will look at how to add the All choice to the menu, which won't be generated from the datasource.

Comments ( 8 )

June 29, 2005

7:28 PM How Templates Work XVI - Additional Navigation and Filtering

The last example showed how to navigate 'upwards' in the RDF graph. By carefully defining the RDF graph and using the right triples we can usually navigate to any part of the RDF data that is necessary in order to get the right results. Usually, however you will want to iterate only over the children of a node using a <member> tag and use a <triple> or <binding> for each predicate of each child that you wish to display. This is the way that the template system was originaly designed to be used and many of the datasources used by Firefox and other Mozilla products work with datasources in this way.

A very uncommon form of navigation you can also do is to navigate upwards using a <member> tag, that is to get all the parents of a node, as in this example:

<conditions>
  <content uri="?start"/>
  <member container="?parent" child="?start"/>
</conditions>

This might be used, for instance, to start at a particular photo and find all of the containers that it is inside.

Sometimes you may wish to change the conditions at a later time. For example, you wish to user to be able to select a value from a list, and the template results should be filtered based on that value. This can be done by modifying the DOM nodes inside the conditions and rebuilding the template. For instance, to apply a filter, you might add a new <triple> element. To remove the filter, the <triple> should be removed again. Let's assume that we've given an id of 'cond' to the <conditions> tag.

function applyFilter(country)
{
  var cond = document.getElementById("cond");
  var triple = document.getElementById("filterTriple");
  if (country) {
    if (!triple) {
      triple = document.createElement("triple");
      triple.id = "filterTriple";
      triple.setAttribute("subject", "?photo");
      triple.setAttribute("predicate", "http://www.daml.org/2001/09/countries/iso-3166-ont#Country");
    }
    triple.setAttribute("object", country);
    cond.appendChild(triple);
  }
  else if (triple) {
    cond.removeChild(triple);
  }
  document.getElementById("photosList").builder.rebuild();
}

The 'country' argument to the applyFilter function holds the value to filter by. If this is set, we add a filter, otherwise we remove it. The code is fairly straightforward. A new <triple> element is created and the object attribute is set to the value to filter by. For example, the resulting triple for the Netherlands might be:

<triple subject="?photo"
        predicate="http://www.daml.org/2001/09/countries/iso-3166-ont#Country"
        object="http://www.daml.org/2001/09/countries/iso#NL"/>

This triple is then appended to the conditions. The triple is given an id so that it can be found later if a different filter is applied. Naturally, we only want to apply one filter at a time, so we can just reuse the same triple for each filter. When removing the filter, we only need to remove the triple from the conditions. This example only adds one triple, but you could add others, or add <member> elements. Whether a triple or member is added or removed, the template must be rebuilt by calling the rebuild method. This method will remove all of the existing generated content, delete all of the internal information pertaining to the results, and start again as if the template was just being examined for the first time. The template will be parsed again and the data examined for new results.

You can view a complete example of this in action. A menulist is used to allow one to select either a specific country, or select All to show all of the photos. When a choice is made, the applyFilter function as shown above is called and the template content gets rebuilt with the desired filter applied.

In this example, the menulist is hard-coded to contain the items that we know are in the datasource. Next, we'll look at also generating this list using a template.

Comments ( 8 )

June 26, 2005

3:53 PM How Templates Work XV - Source Navigation

Triples may also be used to navigate up the graph as well as downwards, following the graph arrows in the reverse direction. For instance, in the original example, we could start at node D and navigate upwards to A and C. The syntax for the triple is the same except that the known variable should be placed in the triple's object attribute and the unknown variable should be placed in the triple's subject variable.

<conditions>
  <content uri="?start"/>
  <triple subject="?relateditem"
          predicate="http://www.xulplanet.com/rdf/relatedItem"
          object="?start"/>
</conditions>

The triple is evaluated in the same manner except that the value of the object can be filled in with the value of the ?start variable. The RDF graph is examined for an arrow pointing in to the node instead of out. In the photos example, we might wish to categorize each photo into several categories. One possibility is to just add another predicate for each photo with a literal value set to the category. Or, we could use a resource for each category. This will allow us to associate additional properties to each category and more easily navigate the graph in a template. In this case, we will categorize each photo by country where the photo was taken using a country predicate.

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns:nso="http://www.daml.org/2001/09/countries/iso-3166-ont#">
  <rdf:Seq rdf:about="http://www.xulplanet.com/rdf/myphotos">
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"/>
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/canal.jpg"/>
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg"/>
  </rdf:Seq>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"
                   dc:title="Palace from Above">
    <nso:Country resource="http://www.daml.org/2001/09/countries/iso#IT"/>
  </rdf:Description>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/canal.jpg"
                   dc:title="Canal">
    <nso:Country resource="http://www.daml.org/2001/09/countries/iso#NL"/>
  </rdf:Description>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg"
                   dc:title="Obelisk">
    <nso:Country resource="http://www.daml.org/2001/09/countries/iso#IT"/>
  </rdf:Description>
  <rdf:Description about="http://www.daml.org/2001/09/countries/iso#IT"
                      dc:title="Italy"/>
  <rdf:Description about="http://www.daml.org/2001/09/countries/iso#NL"
                      dc:title="Netherlands"/>
</rdf:RDF>

A new Country predicate has been added to each photo pointing to another resource. Note that this predicate uses a new namespace so it is declared on the root RDF element. The titles of the two countries are defined near the end of the RDF data. Now that we have countries for each photo, instead of starting at the node 'http://www.xulplanet.com/rdf/myphotos', we could start at a country resource and look for all photos that point to that country. The ref attribute will need to changed to point to the country resource rather that the Seq container of photos.

<hbox datasources="template-guide-ex2.rdf"
      ref="http://www.daml.org/2001/09/countries/iso#IT">

In this example, three triples will be used.

<conditions>
  <content uri="?start"/>
  <triple subject="?start"
             predicate="http://purl.org/dc/elements/1.1/title"
             object="?countrytitle"/>
  <triple subject="?photo"
             predicate="http://www.daml.org/2001/09/countries/iso-3166-ont#Country"
             object="?start"/>
  <triple subject="?photo"
             predicate="http://purl.org/dc/elements/1.1/title"
             object="?title"/>
</conditions>

The first triple is used to get the title for the country. There is only one potential result at this point, the starting node which is 'http://www.daml.org/2001/09/countries/iso#IT'. After the first triple is examined, the data network will look like the following:

(?start = http://www.daml.org/2001/09/countries/iso#IT,
 ?countrytitle = Italy)

Only one result is present since there is only one title available. The second triple is the more interesting one. It is used to look up nodes that have a Country predicate pointing in. It may be difficult to tell whether the builder will look for arcs pointing out from a node or into a node just by looking at the <triple> element. The template builder doesn't know this either until the triple is evaluated and variable substitution is done. Here, the value of the ?start variable is already known for the potential result, so it will be filled in. However, the value of the ?photo variable is not known. Since the object is known and the subject is not, the builder knows to look for a predicate pointing in to a node. There are two photos in the RDF datasource that point to the node 'http://www.daml.org/2001/09/countries/iso#IT', so the existing result will be copied for these two photos. The resulting data after the second triple will look like this:

(?start = http://www.daml.org/2001/09/countries/iso#IT,
 ?countrytitle = Italy,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg)
(?start = http://www.daml.org/2001/09/countries/iso#IT,
 ?countrytitle = Italy,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/obselisk.jpg)

The third triple just grabs the title from the photo as previous examples did, adding a value for the ?title variable for each photo. We can then display these results using the following action body.

<vbox uri="?photo" class="box-padded">
  <image src="?photo"/>
  <label value="?title"/>
  <label value="Country: ?countrytitle"/>
</vbox>

A label for the country will be displayed as well. Naturally, it will have the same value for every photo. Some padding has been added around each photo using the 'box-padded' class. Here is the example.

Comments ( 11 )

June 24, 2005

5:48 PM How Templates Work XIV - Literals in Triples

The triples used so far have all had variables in both the subject and object. However, a string value may be used instead. Since the subject of an RDF arc is always a resource, the subject may be a resource URI. The object attribute may be a resource URI or a literal value. Using a literal as the object of a triple is a common way to filter out specific items. For instance, if items were identified with a type, the data could be filtered to include only items of a particular type.

Here is an example triple that we could use in the photos example:

<conditions>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
  <triple subject="?photo"
          predicate="http://purl.org/dc/elements/1.1/title"
          object="Canal"/>
</conditions>

This new triple has a static value for the object attribute instead of a variable reference. You might be able to guess that it will cause a match for only one of the photos, the Canal photo. The others won't be able to match when evaluating the triple. To look closer, here is the data network after the member has been evaluated:

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg)
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/canal.jpg)
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/obselisk.jpg)

When evaluating the triple, the template builder will iterate over the three potential results found so far. For the first result, the value of the ?photo variable 'http://www.xulplanet.com/ndeakin/images/t/palace.jpg' will be used as the subject, the predicate will be 'http://purl.org/dc/elements/1.1/title', and the object will be 'Canal'. Since there are no variables to fill into the triple, the builder will just confirm that such an triple exists in the datasource. The triple doesn't exist for the first result since the title for the first photo is 'Palace from Above', so the potential result will be removed from the data. For the second result, such an arc does exist, so the result is kept. Like the first result, there is no arc for the third photo, so it is also removed.

The resulting data will look like the following:

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/canal.jpg)

Here is the example.

Naturally, we will need to add a binding for the ?title variable if we wish to display it, or we could just hardcode it since we know the value will be 'Canal'. Usually you won't be filtering on a title though, you would instead filter on a value that acts like a type.

There has to be at least one variable used in a triple in either the subject or the object attributes, or both. You can't have a triple with no variables. That's not an issue though, since it wouldn't be particularly useful. Also, you cannot use a variable in the predicate. Only the subject and object attributes may have variables. Another thing that you cannot have is a triple where both variables would be unknown as in the following:

<conditions>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
  <triple subject="?category"
          predicate="http://purl.org/dc/elements/1.1/title"
          object="?title"/>
</conditions>

In this case when the template builder gets to the triple, neither the ?category nor the ?title variables can be filled in so the builder doesn't know what to generate. The builder won't generate any output in this situation.

The member tag must have variables for both the container and child attributes. It wouldn't be very common to filter for a specific child anyway.

Comments ( 7 )

June 22, 2005

8:48 PM How Templates Work XIII - Other Action Syntax

So far, attribute replacement in an action body has been used to replace an entire attribute with the value of a variable. However, you may also replace only part of attribute's value, or use multiple variables in one attribute. For instance, to include a prefix before a variable value, you can use:

<label value="My name is ?name"/>

The effect will be that the ?name part of the attribute will be replaced by the value of the variable ?name. For instance, if the value of ?name is 'Jake', then the attribute value will be 'My name is Jake'. You can include multiple variables in one attribute if desired:

<label value="My name is ?name and my age is ?age"/>

This technique will work for any variable replacement in the action body, except for the uri attribute since that wouldn't be meaningful. Note that variable names must have a space after them as this is how the end of the variable is determined. That is, '?name?age' is considered to be a single variable with that name, not two variables together. To use two variables, place a space between them. It is sometimes useful though, to concatenate two values together without a space. This can be done by putting two variables next to each other in an attribute value separated by a caret (^).

<label value="?name" class="?gender^?nationality"/>

The caret is considered a separator between variables, however it will not appear in the output. It can also be used to separate a variable with normal text:

<label value="?name" class="?gender^german"/>

These last two examples have been setting the class attribute on a label. The effect will be that a label will have either the 'malegerman' or 'femalegerman' class. In a stylesheet, you could set properties for each of these classes such that different values appear differently without having to use multiple rules.

Although not common, you may also wish to insert a question mark or a caret into an attribute value. To do this, just use two question marks or two carets in a row. For instance:

<label value="What is my name?? My name is ?name"/>

In this example, the label might be 'What is my name? My name is Jake'. Note that a caret only has a special meaning at the end of a variable, thus two in a row are only needed after a variable.

One last thing to point out is that since the only characters that can separate a variable are a caret, a space or the end of the attribute, this means that any other character is valid as a variable name. However, for readability, you should restrict variable names to letters, numbers and perhaps hyphens to separate words.

The description added in the last example might be a long string of text for some of the photos. It may be desirable to have the text wrap by placing it inside a <description> element. This means that we want to do variable replacement as text, not as an attribute value. A special tag is used for this purpose, the <textnode> tag. It has one attribute, the value attribute, which may use variable substitution like other attributes. However, the <textnode> element is not copied into the generated content, but instead a DOM text node is created with the value of the value attribute as its contents. For instance, if the template contained:

<description><textnode value="?description"/></description>

The resulting generated content might be:

<description>View from the top of the tower looking east of the Doges Palace</description>

Note that the <textnode> has been replaced with the substituted value attribute. Unfortunately, a bug can make this appear to not work at times. Recall that the template builder doesn't load the datasource before processing a template. As the datasource loads, the rules are examined with the new data as it arrives. This causes rules to create matches as the data loads. However, variables determined from a binding are evaluated using a much simpler process. The bug is that this code path for bindings doesn't handle the textnode element properly. Thus, if you use a variable set in a binding, you must ensure the datasource is loaded before the template is built, or just rebuild the template. Another possibilty is to rearrange the RDF such that the values, in this example, the descriptions, are specified before the containers. This may seem a bit confusing, but hopefully, this bug, if you do encounter it, should be fixed soon.

Comments ( 3 )

June 19, 2005

4:53 PM How Templates Work XII - Bindings

We can add more triples to the previous example to show more information. For example, a description could be added to a photo. To do this all we need to do is add the necessary data to the RDF datasource and add another <triple> element to the template's conditions.

<conditions>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
  <triple subject="?photo"
          predicate="http://purl.org/dc/elements/1.1/title"
          object="?title"/>
  <triple subject="?photo"
          predicate="http://purl.org/dc/elements/1.1/description"
          object="?description"/>
</conditions>

It works similarly to the previous triple. The ?photo variable is filled in with the known value and then the arc is looked up in the datasource, filling in the value for the ?description variable. The ?description variable would then be used in the action body. Let assume though, that we are only going to add a description to one of the photos in the datasource; the other two photos will not have a description. This may mean the description is not known, or that it wasn't filled in by the user.

<rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"
  dc:title="Palace from Above"
  dc:description="View from the top of the tower looking east of the Doges Palace"/>

If you try a full example based on this data, you will notice that only one result has been generated. This is because only one item has a description. Here is the data after the first <triple> has been evaluated, but before the description triple has been examined:

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg,
 ?title = 'Palace from Above')
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/canal.jpg,
 ?title = 'Canal')
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg,
 ?title = 'Obelisk')

The second triple will add a ?description for the first photo, adding a fourth variable-value pair to the existing data. However, when the builder doesn't find any value for a condition, the entire potential result is removed. For the second photo, the datasource doesn't have any matches for the description, so that potential result will be removed. The same happens for the third photo. In the end, only one photo remains.

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg,
 ?title = 'Palace from Above',
 ?description = 'View from the top of the tower looking east of the Doges Palace')

Thus, only one match exists, so only one set of content is generated.

Sometimes, it would be useful to have triples that match conditionally, that is , have a triple that doesn't cause a result to be removed as a possible match. This is done with a <binding> element. This tag doesn't go in the <conditions> block but instead inside a <bindings> element. The syntax is as follows:

<rule>
  <conditions>
    ...
  </conditions>
  <bindings>
    <binding subject="?photo"
             predicate="http://purl.org/dc/elements/1.1/description"
             object="?description"/>
  </bindings>
</rule>

The description triple has been changed to a <binding> element, but the attributes are the same. This allows a match to occur even if the description is not specified in the data. The template builder examines bindings after all the conditions have been applied. It has already determined, in this example, that three matches have been found. The builder continues by filling in the values for any bindings. They are evaluated in a similar although simpler mannner as the triples. The value of the ?photo variable is known for each match, the datasource is examined for the description, and the value of the ?description variable is filled in. The effect is three matches, only one of which will display a description. The photos that don't have a description will be treated as if the description was blank. That is, the ?description variable will be replaced with an empty string when analyzing the attributes in the action body.

Here is this example.

You can have more than one binding if you wish. The others will be evaluated in a similar way. For instance, the title triple could be moved to a binding such that it could be optional also.

Comments ( 9 )

June 16, 2005

7:04 PM How Templates Work XI

Let's look a more useful example, this time for a template that will show a list of photos. In this situation, an RDF container will be used to hold the list of images.

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/">
  <rdf:Seq rdf:about="http://www.xulplanet.com/rdf/myphotos">
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"/>
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/canal.jpg"/>
    <rdf:li rdf:resource="http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg"/>
  </rdf:Seq>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"
                   dc:title="Palace from Above"/>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/canal.jpg"
                   dc:title="Canal"/>
  <rdf:Description rdf:about="http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg"
                   dc:title="Obelisk"/>
</rdf:RDF>

In this example, we have three images, which can be identified by urls. The resource uris correspond to their actual urls although this isn't necessary. Each image also has one property, the image's title. A template which displays this information is very simple to create. Unlike previous examples where we iterated over a property to navigate the graph, here we want to iterate over the children of an RDF container. The container, an RDF Seq, has the uri 'http://www.xulplanet.com/rdf/myphotos'. This will be the starting point of the navigation. We want the endpoints to be the three images. First, we set the datasources and ref attributes as needed:

<vbox datasources="template-guide-ex11.xul"
      ref="http://www.xulplanet.com/rdf/myphotos">

This time, we need to use a new condition, the <member> condition as well as a <triple>.

<conditions>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
  <triple subject="?photo"
          predicate="http://purl.org/dc/elements/1.1/title"
          object="?title"/>
  </conditions>

The seed is set in a similar manner as the previous examples, effectively creating a single result with the ?start variable set to the reference resource 'http://www.xulplanet.com/rdf/myphotos'. The same starting variable is used in this example, but you can of course use any variable you wish.

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

The <member> condition is used to iterate over the children of a container (or the reverse). First, any known variables are filled into the member condition for the current result. There's only one result so far; the member element's container attribute is set to value of the ?start variable of this result. This will result in the following:

<member container="http://www.xulplanet.com/rdf/myphotos" child="?photo"/>

As with processing a triple, the builder will now try to find as many values for the ?photo variable as possible and create potential results using them. The container attribute specifies the container and the child attribute specifies the children. In the RDF data, the container "http://www.xulplanet.com/rdf/myphotos" has three children, so there are three possible values for the ?photo variable. If that node had no children or wasn't a container, there would be no possible results. The data network will now look like this:

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg)
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/canal.jpg)
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/obselisk.jpg)

The <triple> is evaluated next, and it will be examined for each potential result found so far. The builder will first fill in as many variables as it can. For the first result, the value of the ?photo variable is known, so the triple will be evaluated like so:

<triple subject="http://www.xulplanet.com/ndeakin/images/t/palace.jpg"
        predicate="http://purl.org/dc/elements/1.1/title"
        object="?title"/>

The builder next calculates the value for ?title using the predicate 'http://purl.org/dc/elements/1.1/title'. In the RDF, the 'palace' resource has a value 'Palace from Above', so it will be added to the data network, assigned to the ?title variable. Note that this value is a literal rather than a resource.

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg)
 ?title = 'Palace from Above')

The process continues in a similar manner for the other two results. In the end, the network will contain the following data:

(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/palace.jpg)
 ?title = 'Palace from Above')
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/canal.jpg)
 ?title = 'Canal')
(?start = http://www.xulplanet.com/rdf/myphotos,
 ?photo = http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg)
 ?title = 'Obelisk')

Since the <triple> is the last condition, three matches have been found. The action body might look like the following, which displays the image using its url and title in a label. You might note that the image's src attribute uses the member variable ?photo

<action>
  <vbox uri="?photo" align="start">
    <image src="?photo"/>
    <label value="?title"/>
  </vbox>
</action>

It shouldn't be too difficult to tell what would appear in the window in this example. You can see if you guessed correctly by viewing the example.

Comments ( 8 )

June 13, 2005

7:28 PM How Templates Work X

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. In this example, for the top level generation the parent insertion point is the element with the datasources attribute, 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>
    <rule>
      <conditions>
        <content uri="?start"/>
        <triple subject="?start"
                predicate="http://www.xulplanet.com/rdf/relatedItem"
                object="?relateditem"/>
      </conditions>
      <action>
        <hbox uri="?relateditem">
          <button label="?start"/>
          <button label="?relateditem"/>
        </hbox>
      </action>
    </rule>
  </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 rules 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> condition 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)

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, 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.

Comments ( 5 )

June 11, 2005

11:10 AM How Templates Work IX

The previous example generated only a set of buttons, but the action body may contain additional content. For instance, you might want to add a label to each item.

<action>
  <hbox uri="?relateditem">
    <label value="Related Item:"/>
    <button label="?relateditem"/>
  </hbox>
</action>

In this example, the <hbox> will be generated for each result, assigned an id of the value of the ?relateditem, and the label and button will be added inside it. The button's label will be the value of the ?relateditem variable. You would only use the uri attribute on a single element since only one of the generated elements should be given a particular id.

Although the uri attribute should only be on one element, it does not have to be the outermost element in the action body. You can place other elements outside this to serve as containers for all the results. One difference is that this content is only generated once, not for every result. Only the content at the element with the uri attribute and below is copied for each result. For example, if the example was modified to the following:

<action>
  <toolbar>
    <button uri="?relateditem" label="?relateditem"/>
  </toolbar>
</action>

Here, only the button would be repeated for each result; the toolbar will only be generated once. The toolbar is created just before the content for the first result is generated. The effect will be a toolbar with a set of three buttons inside it. Of course, in this simple example you would really just make the toolbar the outer element with the datasources attribute rather than placing inside the action.

So far we have only be using the ?relateditem variable since that is really the only useful variable that is available. We could also use the ?start variable. Recall the results:

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

We could display the value of the ?start variable in the results if desired:

<action>
  <hbox uri="?relateditem">
    <button label="?start"/>
    <button label="?relateditem"/>
  </hbox>
</action>

For the first button, the value of the variable ?start will be looked up in the result data while the second button will use the ?relateditem variable. Since all three results have the same value for the ?start variable, the result will be that the first buttons in each row will all have the same label. Here is an image of this example

You'll notice that the second row has an extra two buttons. We'll see why next.

Comments ( 6 )

June 9, 2005

6:58 PM How Templates Work VIII

The content to generate in a template is specified using the <action> element which should be a direct child of a <rule> element. The content goes directly inside the <action> element. This content will be copied for each matching result and inserted into the document. Let's look at a simple example first.

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

This action contains only one element, but you can put as many or as few elements as you need. In this case, a button will be created for each result. There are three results, so three buttons will be created. Here is the example, and an image of what it looks like:

The template builder iterates through the three results, processesing the body of the action for each one in turn. The uri attribute on the button is used to specify the ending or member variable. In this example, there's only one variable to use, ?relateditem, since ?start is the starting point and the start and end points cannot be the same. There are a number of things that will happen for each result. Let's look at the results again:

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

The builder will start with the first result. The <button> element will be copied and inserted into the document after the template. The id attribute of the new element will be set to the same value of the member variable, ?relateditem. You could think of this as changing the uri attribute to the id attribute, and replacing the variable. Since the first result has a value of "http://www.xulplanet.com/rdf/B" for the ?relateditem variable, the id will be set to this value.

Then, the remaining attributes on the element are examined and any variables are replaced in place. That is, the text ?relateditem in the label attribute will be replaced with the string "http://www.xulplanet.com/rdf/B" for the first result. In the image, you can see that the label for the first button does indeed have this value. Processing is now complete for the first result, so the builder moves on to the next result. For result B, the builder would have generated the following content:

<button id="http://www.xulplanet.com/rdf/B" label="http://www.xulplanet.com/rdf/B"/>

Naturally, you wouldn't use an id attribute inside a template action since the id would be replaced anyway. In fact, any ids you put inside a template action will be ignored. However, you may use ids on the other parts of the template, such as within the conditions, if you wish to change the conditions and rebuild the template. You can use getElementById to get at particular results, for instance document.getElementById("http://www.xulplanet.com/rdf/C") would retrieve the second generated button.

After all the results have been examined, the DOM tree will look like the following:

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

Since the <template> tag is hidden, the effect will be like in the image, three buttons with the labels of the data in the datasource.

Next, we will look at a more complex example.

Comments ( 7 )

June 8, 2005

6:59 PM How Templates Work VII

After, the <content> tag has been examined, the builder moves on to the next condition, the <triple> which looks like this:

<triple subject="?start"
        predicate="http://www.xulplanet.com/rdf/relatedItem"
        object="?relateditem"/>

The <triple> condition is used to follow arcs or arrows in the RDF graph. The predicate attribute specifies the labels of the arrows to follow. In the triple used here, the predicate is "http://www.xulplanet.com/rdf/relatedItem", so we know that the builder will look for arrows with that label. The builder can either follow the arrows in a forward or backward direction, but only one direction per condition. It determines which direction to use by examining which data is known and which data is not known yet. Recall the data in the potential results set:

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

This was the seed data created by the <content> condition. You might be able to guess that the builder fills in the value of the ?start variable as the triple's subject, giving something like this:

<triple subject="http://www.xulplanet.com/rdf/A"
        predicate="http://www.xulplanet.com/rdf/relatedItem"
        object="?relateditem"/>

The builder doesn't actually change the triple, but this might clarify how the builder is working. The builder looks at both the subject and object of the triple and tries to resolve any of the variables using the known data. The ?start variable has a value "http://www.xulplanet.com/rdf/A", so that is filled in. The ?relateditem variable doesn't have any known value, so it will be left as is. Once the variables are filled in, the builder can query the RDF graph.

The query will look for all arrows that start at the node "http://www.xulplanet.com/rdf/A" with the predicate, or arrow label "http://www.xulplanet.com/rdf/relatedItem". Since ?relateditem isn't known, the builder will allow any value for the node the arrow points to, and will look in the datasource for all possible values. In a <triple> condition, the subject is always the start of an arc, while the object is what it points to. For this triple, the builder will follow the arrows in the forward direction. Here is the RDF graph again:

Starting at node A and following the relatedItem arcs, we can see that there are three possible values for the ?relateditem variable, B, C and D. This is new data, so the builder adds it to the graph. Since three values have been found, the network will now have three potential results:

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

You may note that the ?start variable is repeated for each result. This is because the builder copies the existing data for each new potential result and adds the new data. Internally, this isn't quite true; the builder actually maintains only one copy of the similar data but uses data structures in such a way which make it appear as if it is duplicated.

You may find this a bit confusing, but this should become clearer later with more specific and practical examples.

Since the <triple> was the last condition, the builder moves on to the content generation phase, creating matches out of the three potential results.

Comments ( 7 )

June 6, 2005

3:22 PM How Templates Work VI

Let's look at a simple rule with two conditions. The conditions are enclosed in a <conditions> tag which is placed directly inside the <rule> tag. Each condition is placed inside the <conditions> tag.

<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
         ref="http://www.xulplanet.com/rdf/A" hidden="true">
  <template>
    <rule>
      <conditions>
        <content uri="?start"/>
        <triple subject="?start"/>
                predicate="http://www.xulplanet.com/rdf/relatedItem"/>
                object="?relateditem"/>
      </conditions>
      ...
    </rule>
  </template>
</vbox>

This rule has two conditions, each specified with a different tag. The template won't generate anything yet since we still need to fill in the content to be generated which goes in the missing part after the conditions. However, the template builder will be able to compile the rules and examine them as described earlier.

The builder needs to start with a single result as the seed result. This is done with the <content> tag. It indicates that we are going to use a starting point when navigating the graph. Obviously, since you need to start somewhere, you will have to use a <content> tag and it should be the first condition. Also, because we can only have one starting point, only one <content> tag can be used. The seed result will be created like this:

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

The variable ?start is determined from the tag's 'uri' attribute. You can use any variable you want; it's common to use the variable ?uri. However, all rules must use the same starting point variable. So if a second rule were used, it would also need to use the ?start variable. The value of ?start is set to 'http://www.xulplanet.com/rdf/A'. You'll notice that this is the value of the ref attribute which is the desired starting node in the RDF graph. Thus, the ?start variable becomes the container or reference variable.

The <content> tag doesn't do anything else at this point, meaning it doesn't add anything else to the network of potential results, so processing continues on to the next condition, the <triple>

Actually, in the current templates implmentation, the above description isn't quite correct. The seed is a actually an internal variable set to the container, in this case, the <vbox>, and the ?start variable is set to the ref later, but that is a minor detail that doesn't make templates more understandable. For this discussion, assume that so far we have a single potential result as above.

Comments ( 9 )

June 4, 2005

8:07 PM How Templates Work V

During rule processing, the template builder builds up a network of information such as what possible results are available, where content should be generated, and information that indicates what to do when the RDF datasource changes. This network of information remains for the lifetime of the template, or until it is rebuilt. The template builder uses an method based on the RETE algorithm to match data. This allows for a fairly efficient means of updating results when, for instance, a new statement is added to the RDF graph. Rather than rebuild the entire template, the algorithm allows only specific parts of the network of information to be re-examined. A similar method can be used when removing RDF statements.

While the information network created by the template builder contains a number of different pieces of necessary information, for the purposes of this discussion, we will only be interested in the list of possible results. The builder begins with a single possible result, called the seed. The builder processes each of a rule's conditions in sequence. To do this for a particular condition, it iterates over the possible results found so far and either accepts each result or rejects each result. For the first condition, only the seed will be available as a possible result. At each step, new possible results may be added, or more information pertaining to an existing result may be added to the network. Naturally, a rejected result will be removed. Once all results have been examined, the builder moves on to the next condition. Once all conditions have been analyzed, any results which still remain go on to become matches. The matches are the endpoints and will cause content to be generated. So, to summarize:

  1. Start out with a one possible result as the seed
  2. Iterate over the results determined so far and augment them with additional data
  3. Add any new possible results
  4. Remove any rejected results
  5. Repeat steps 2 to 4 for each rule condition
  6. Once done, all remaining results become matches

Each possible result is made up of a set of variable-value pairs. For instance, a result would look something like the following:

(?name = Fred, ?age = 5)

This result has two variables, ?name with the value 'Fred' and ?age with the value 5. Variables begin with a question mark, and values are RDF resources or literals. Here we will use strings for the values so they are easier to read. If we had two results, they might look like this:

(?name = Fred, ?age = 5)
(?name = Mary, ?age = 12)

This is how we'll represent the potential results in this and the following discussions.

Later, we might have a condition which removes all Male results. So, our results after this might look like the following:

(?name = Mary, ?age = 12, ?gender = Female)

This condition has removed Fred from the potential results and added the ?gender variable for Mary. This is typical of how a rule condition works, by adding additional variables to a result and filtering out those that don't match a particular value. If this was the last condition, Mary would go on to become a match to be displayed.

Comments ( 5 )

June 3, 2005

4:10 PM How Templates Work IV

Once the template builder has compiled the rules, rule processing and content generation can begin. The template builder generates content lazily, that is, it processes as little as need, and only continues when necessary. For instance, consider the example below:

<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
         ref="http://www.xulplanet.com/rdf/A" hidden="true">
  <template>
    ...
  </template>
</vbox>

The <vbox> is hidden as indicated by the 'hidden' attribute. Since any content that would be generated wouldn't be displayed anyway, the template builder doesn't do anything, putting off work until later. If you show the vbox by setting the hidden state to false, the template builder will be invoked and the content will be generated.

Does this mean that templates cannot be used inside hidden areas of the UI? No, you can still do that. Changing the hidden state of an element isn't the only way to cause content to be generated. Calling a DOM API which needs to get at the generated content will cause the template builder to generate output. For example, just calling the code like the following on the hidden vbox above will start off the template builder.

var length = vbox.childNodes.length;

This request to return the number of children of the vbox will make the template builder process the rules and output content. Once done, the correct length can be returned.

All of this is transparent to the XUL developer. When the template builder decides to start generation is determined automatically and you don't need to do anything special to get this to happen. However, there are two cases where content is not generated automatically: menus and child tree items.

Content inside a menu is not generated until the menu is opened. This makes sense since the user can't see the contents of the menu until it is open. However, it also means that the DOM API usage, such as an attempt to get the number of child nodes as above, will also not include generated items until the menu is opened. This is an important distinction. That means that you will not be able to rely on being able to retrieve the generated menu items until the menu is opened. A similar rule applies for child tree items. The children are not generated until the user presses the twisty to open the container, or a script opens a row.

Lazy generation comes in handy for menus and trees especially when dealing with recursive items. It would be rather time consuming to generate output for every item in a tree, even for those not displayed, so the template builder doesn't do so.

The template builder is even lazier. If the generated content itself contains hidden elements, those child elements will not be generated until necessary. When building content, the builder iterates down the node tree, copying and building only when needed.

Next, we'll look into how the template builder processes the rules.

Comments ( 9 )

June 2, 2005

6:26 PM How Templates Work III

A XUL template is made up of series of rules. Each rule contains two things, a set of instructions for navigating through an RDF graph and some XUL content to generate. Given a starting point, the template builder will evaluate the navigation instructions for each rule and will generate a series of endpoints matching that rule. The corresponding content will then be generated. It's actually more complicated than that but this is the basic idea.

There are two syntaxes for declaring the rules, the simplified syntax and the extended (or full) syntax. As its name implies, the simplified syntax is simpler but is limited in the type of data that it can iterate over. It may be used to iterate over one and only one arc (or arrow) in the RDF graph. The extended syntax may navigate anywhere in the graph. Almost always, the simplified syntax will be used to iterate over a set of children of an RDF container like a Seq. An RDF Seq is a container that contains children in a specific order. The template will generate these results in that order.

The simplified syntax is a subset of the extended syntax, that is, it is possible to rewrite a rule that uses the simplified syntax using the extended syntax. In fact, the template builder will internally convert the simpler rule into an extended syntax rule for use. Neither syntax is preferred; you may use the extended syntax exclusively if it feels more natural to you. Note however, that the simplified syntax uses a slight optimization when using more than one rule which the extended syntax does not use. Well look at this in more detail as we look more at rules.

Each rule is declared using the <rule> tag, which you would place directly inside the <template> element. You may have as many rules as you wish, or you may have only one. When using the simplified syntax, you may omit the <rule> element when you have only one rule as its usage will be implied. The extended syntax, however, always requires the <rule> element.

Here is the outline of the template syntax so far.

<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
         ref="http://www.xulplanet.com/rdf/A" flex="1">
  <template>
    <rule>
      -- rule content goes here --
    </rule>
    <rule>
      -- rule content goes here --
    </rule>
  </template>
</vbox>

When the template builder starts processing, and after it has started the datasource loading, it first must compile the rules. This step involves working through the rules and processing them into internal structures. Thus, changing the rule elements around dynamically doesn't affect anything. However, rebuilding the template (using the builder.rebuild method) will recompile the rules and reapply the template again. This means that you can change the rules using DOM methods, rebuild the template, and get different results.

Comments ( 7 )

June 1, 2005

2:45 PM How Templates Work II

RDF is, in mathematical terms, a labeled directed graph. That means that RDF is a graph of nodes and arrows between them where each node and arrow has some label. Since it's a graph, arrows can point all over the place and nodes can have any number of arrows pointing out of them and pointing at them. And also because it is a graph, there is no real starting point or root node so you can just start anywhere. In the picture below, you can see that node A at the top has arcs pointing to B, C and D. As well, C has an arc pointing to D. You could have arcs pointing elsewhere, for example node D could have an arc pointing back to A. To navigate around, you could start at node A and navigate around the graph following the arrows to B, C or D. Or you could start at B and go to A and then go to C and D. No requirement exists to follow the arrows in the direction they point; you can easily go the other way. The picture was generated from the W3C's RDF validator, a good place to go to check if your RDF is valid.

The text in red are the labels for the arrows, called predicates. In this example, all the arrows have the same label. Usually, this won't be the case. Templates provide a means of navigating around using only arrows with specific labels. Here is the serialized RDF/XML for this graph.

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:rel="http://www.xulplanet.com/rdf/">
  <rdf:Description rdf:about="http://www.xulplanet.com/rdf/A">
    <rel:relatedItem rdf:resource="http://www.xulplanet.com/rdf/B"/>
    <rel:relatedItem rdf:resource="http://www.xulplanet.com/rdf/C"/>
    <rel:relatedItem rdf:resource="http://www.xulplanet.com/rdf/D"/>
  </rdf:Description>
  <rdf:Description rdf:about="http://www.xulplanet.com/rdf/C">
    <rel:relatedItem rdf:resource="http://www.xulplanet.com/rdf/D"/>
  </rdf:Description>
</rdf:RDF>

For a XUL template query, you first need to select a starting point in the RDF graph. Once you have selected a starting point, you use a number of statements which indicate where to go next when navigating the graph. Eventually, you will end up with a set of nodes you consider the endpoints of your query. These become the results and content would be generated for each of these results. Say you start at A. You could navigate to B, C and D and generate three blocks of output. Or, you could start at D and follow two arrows back. This will get two results, A and B. Look at the graph to see if you can see why two results would be generated in this case.

In XUL template terminology, the starting point is called the container or reference point and the endpoint is called the member. It is so called because it is most common to gather the list of the members, or children, of a container. But this doesn't have to be the case. Any starting point and ending points will do.

Nodes in RDF are identified by a string value. There are two types of nodes in RDF, resources which usually represent 'things', and literals which are values like the names of things, the dates of things, the sizes of things, and so on. A literal's value is, for example, the name of the thing, such as 'Fred'. A resource's value is a URI which for your own RDF data you can just make up. We'll use the URI of the resource nodes in a template. In the image, the resource URI's are the blue labels of each node. There are no literals in this example, but we'll see some later.

Let's say we want the starting point to be A from the above example graph. We will use A's URI (http://www.xulplanet.com/rdf/A) as the reference starting point. In a XUL template, you specify the starting point using the 'ref' attribute. Here is an example:

<vbox datasources="http://www.xulplanet.com/ds/sample.rdf"
      ref="http://www.xulplanet.com/rdf/A" flex="1">

This is an indicator that we want to construct a XUL template using the reference point with the URI 'http://www.xulplanet.com/rdf/A'. Next, we'll see how to construct the template.

Comments ( 9 )