Simple Query Syntax

When iterating over the children of an RDF container, there is a simpler query syntax which may used. It may also be used when iterating over only one predicate. Simple RDF graph navigation such as this is common, so the simpler syntax is usually used in this situation since it avoids extra tags, although the simple syntax is not more or less efficient, at least when a single query is involved. A simple query is equivalent to a query with only the content tag and a member tag, as well as optionally a set of triples from the child node. At its simplest, the simple query syntax is equivalent to the following:

<query>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
</query>

The template builder uses the simple query syntax whenever a template does not have a <query> element. If a <query> element is present, the full syntax is used instead. In the simple syntax, the builder will use the default query shown above, although the variable names are randomly generated.

Since the photos list iterates over the children of a container, we can use the simple syntax. Here is what it might look like:

<template>
  <vbox class="box-padded" uri="rdf:*">
    <image src="rdf:*"/>
    <label value="rdf:http://purl.org/dc/elements/1.1/title"/>
  </vbox>
</template>

There is no <query> or <action> element used. Instead, the builder uses a default query, and the action is placed directly inside the <template> element. You can see that this code is much simpler than the full syntax. To understand how this works, let's examine how the builder processes a simple query. First, it evaluates the default query as above, except that no variables are used, or at least, not ones that are used externally. In reality, the builder could be considered to convert a simple query into an extended query, so that it can be processed in the same way. After the default query statements are evaluated, the data network will look something like this:

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

The numbers are used here for the variable names, but they are really just randomly generated so you can't refer to them in any way. The member data, or results, are held in the variable represented here by '?2'. Three matches have been found so the content will be duplicated three times.

There are several attributes in the example XUL content above that have values prefixed with 'rdf:'. Since you can't declare variables in the simple syntax, a different way is used to grab RDF data. The 'rdf:' prefix means look up a predicate pointing out of the node for that result (the child or member node). For example, the label's value attribute has a value of rdf:http://purl.org/dc/elements/1.1/title'. This means look up the value of the predicate http://purl.org/dc/elements/1.1/title' pointing out of the current result. Of course, it should be obvious that this causes the value attribute to be set to the photo's title.

You can get other predicates in the same way, just by using the predicate uri and prefixing it with 'rdf:'. You can also combine two in one attribute by separating them with a space or a caret (^) just as you can with the full syntax. For example:

<label value="rdf:http://purl.org/dc/elements/1.1/title http://www.xulplanet.com/rdf/country"/>

The 'rdf:' form is really equivalent to the <binding> tag in the full syntax. The subject of the binding is the result member resource, the predicate is the string that comes after 'rdf:' and the object isn't necessary as the value is replaced directly in the attribute. As with bindings, the value is not required to match, so the data doesn't have to exist in the RDF graph. If one photo doesn't have a title, it will be replaced with an empty string.

The special value 'rdf:*' means the uri of the result resource, rather than referring to a predicate. It would be equivalent to ?photo variable in this example if the full syntax was used. You can see in the example that the value 'rdf:*' is used in two places, the uri attribute on the hbox and as the src attribute for the image.

Here is the photos example using the simple syntax. The filtering isn't shown in this example. It is still possible to do filtering using simple query and we'll look at this below.

Simple Query Conditions

Simple queries also use a simpler way of handling triple elements to filter out unwanted results. It allows you to filter for results that have certain predicates with specific values. For instance, you may filter results that have a certain category or country. You can only filter on predicates pointing out of the member resource. That is, you cannot filter on predicates pointing into the member resource nor can you cannot filter based on predicates pointing out of other resources. For that, you need to use the full syntax.

The triples to check are specified using attributes on the rule element (thus, a rule element should be used). The namespace of the attribute and the attribute name combine to form the predicate you wish to filter by and the value of the attribute will be the value to filter by. Any results that match the criteria are accepted and any that do not match are rejected. You can use multiple attributes to filter by several criteria. In this case, all of the criteria must match for the result to be accepted.

For example, to filter for photos with a specific country:

<hbox id="photosList" datasources="template-guide-photos4.rdf"
      ref="http://www.xulplanet.com/rdf/myphotos"
      xmlns:r="http://www.xulplanet.com/rdf/">
  <template>
    <rule r:country="http://www.daml.org/2001/09/countries/iso#IT">
      <vbox class="box-padded" uri="rdf:*">
        <image src="rdf:*"/>
        <label value="rdf:http://purl.org/dc/elements/1.1/title"/>
      </vbox>
    </rule>
  </template>
</hbox>

This example shows how a single attribute may be used to filter for only those results that have a country set to 'http://www.daml.org/2001/09/countries/iso#IT'. Photos that do not have this country will not have any content generated for them. The attribute has a namespace that, when expanded, becomes 'http://www.xulplanet.com/rdf/country'. This syntax is much like how predicates are the specifed in the RDF/XML.

This form of attribute syntax on a rule is equivalent to a <triple> in the extended syntax. In fact, the builder will internally convert the attribute into the same compiled form that would be used for a <triple>. The equivalent triple for the above example might be:

<triple subject="?photo"
        predicate="http://www.xulplanet.com/rdf/country"
        object="http://www.daml.org/2001/09/countries/iso#IT"/>

Adjusting Simple Query Conditions

The simple syntax is limited in the kind of filtering it can do, however it is often sufficient for many purposes. Naturally, if you want to set a filter dynamically, as the photos example does with a menulist, you will need to set the attribute on the rule element and rebuild the template.

function applyFilter(country)
{
  var rule = document.getElementById("filterRule");
  if (country){
    rule.setAttributeNS("http://www.xulplanet.com/rdf/", "country", country);
  }
  else {
    rule.removeAttributeNS("http://www.xulplanet.com/rdf/", "country");
  }

  document.getElementById("photosList").builder.rebuild();
}

This version of the applyFilter function only needs to set or remove the attribute on the rule as necessary. Note that the namespace aware functions (with the suffix NS) need to be used to set or remove attributes with namespaces. This example assumes that the rule has been given an id of 'filterRule'. Note that the menulist itself must use the extended syntax since it doesn't iterate over the children of a resource.

Filtering Using Multiple Tests

As mentioned earlier, you can filter by several criteria by using multiple attributes. For instance:

<rule id="filterRule"
      dc:title="Obelisk"
      r:country="http://www.daml.org/2001/09/countries/iso#IT">

This rule filters on two criteria which must both match. Rules will apply all the attributes as conditions except for the id attribute, as well as some special attributes, which are ignored. These special attributes are useful when handling multiple rules, which will be the subject of a later topic.