XUL:Template Builder Arch

From MozillaWiki
Jump to: navigation, search

The template builder consists of four parts, that can be split without much pain:

= Components

= 1. Content Generation

Takes a set of variable bindings and a unique ID to refer to the generated content, and does the content generation. If content for that ID already exists, it pulls out the old content before regenerating.

= 2. Binding Generation

Takes input from a data source and translates it into a set of bindings (param => value) and a unique ID to refer to those bindings.

= 3. Binding Update

Takes notification or other input from a data source and translates it into a set of bindings similar to #2, notifying observers that the content for the ID that refers to that set needs to be updated.

= 4. Template Matching

Takes a set of bindings and an ID, and looks for rule matches for each binding set.

= Binding Language

Besides supporting param => value pairs, the binding language must also have explicit unambiguous support for indicating whether a) something is a container or not; b) how many elements are in the container (empty or not empty). The "something" here is a chunk of bindings with an ID; that's the basic unit of data that gets passed around. It can look like a js object:

   var something = {
       id: "rdf:$deadbeef",            // required
       numChildren: -1,                // required
       // remainder purely for template matching and substitution
       Name: "Some Name",
       Length: 500,
       Priority: 3

= Template Matching Language

How do matches get specified? The template builder should only deal in terms of a "matching" language, not a "query" language -- the query language should be left up to the binding generation phase, that can take a query in whatever format is convenient and output bindings for input into the template matching system. I don't think that something like xpath or xquery is useful here -- the language should essentially specify filters, and not generate new binding sets.

= Overall picture

Something like:

   [Binding Generation] \\
                         - {bindings} - [Template Matching] - {bindings and matched template} - [Content Generation]
   [Binding Update]     /

Some more notes/ideas:

{bindings} is an array of object chunks as described above; it's the results of the datasource-specific query which happens in the binding generation stage. It must have an "id" and also a "numChildren" (-1 indicates not a container).

If it has children, the binding generation stage must be able to identify its children based on the "id". Essentially, binding generation will (in theory) start with a single base reference (currently we call this "ref" in the rdf case), and produce bindings for feeding in to the rest of the cycle for the ref's children.

The template matching will take simple rules based on the attributes present in the bindings, and decide which template to apply. If it wants to do something with the item's children, it must explicitly invoke another template pass with the root set to the current item's ID. So, maybe something like this... the matching language is bogus, i'm not sure what format those should take... also note the externally-defined template-body elements; using that and then allowing multiple template-apply's might allow for sharing of template chunks. (Hey look, don't have to escape <'s any more!)

   <template id="item-template"
     <template-match rule="isContainer && $Priority >= 2">
       <template-apply ref="high-priority-body" />
     <template-match rule="isContainer && $Priority < 2">
       <template-apply ref="normal-priority-body" />
       <label value="$Name" />
   <template-body id="high-priority-body">
     <hbox class="high-priority">
       <template ref="item-template" root="$id" />
   <template-body id="normal-priority-body">
     <hbox class="normal-priority">
       <template ref="item-template" root="$id" />

And then finally use the template somewhere:

   <vbox class="item-list">
     <template ref="item-template" root="some-datasource:/my/things" />

If a set of bindings is NOT matched by the template matching, it should inform the content builder of the lack of a match. This is to allow for changing which template (if any) matches a set as the data gets dynamically updated, giving the content generator a chance to pull the generated content of that id from the result tree. For straight updates, the generator should remove the old chunk of content with that id, and regenerate based on the new id and new template.

[roc] Pike asked me to put this here. Please move this text if it's not appropriate.

XBL lets you bind anonymous generated content to arbitrary XML elements. It supports CSS styling scoped to the generated content, introduction of generated containers between the bound element and its children, inheritance of attributes, dynamic update, and other cool stuff. It would be cool if we could reuse this very large hammer as part of a template system.

Peter Wilson. Please forgive me if I am stating the obvious. For all the talk of templates there is none of presentation,validation and collation. Is it possible to have a variant of XBL which can map template variables to xbl properties and visa-versa for use in content generation? I have put together a few ideas http://wiki.mozilla.org/XUL_Talk:Priority_List#XUL:IOMapping

NeilDeakin: architecturally, this model is similar to the existing template builder. Certainly from the XUL developer's perspective anyway. I really don't like the pseudo syntax described above. It's twice as complicated as the equivalent code would be using a slightly enhanced version of the existing template builder.

XUL:Vlad Vukicevic: Yep, I'm hoping that we can reuse chunks of code from the current template builder. As for the pseudocode, I'm not attached to it; it was just the first thing that came to mind. The current syntax seems too tied to RDF though, no? At least for the matching and the binding.. the other stuff is fine, though. I'd still like a way to allow for external template rule bodies, though; being able to share those seems like a good thing.

NeilDeakin: using the existing template syntax, the above example could be something like this, assuming an RDF source:

   <vbox datasource="some-datasource:/my/things" ref="whatever">
       <rule iscontainer="true" where="http://www.example.com/rdf/priority >= 2">
         <hbox uri="rdf:*" class="high-priority"/>
       <rule iscontainer="true">
         <hbox uri="rdf:*" class="normal-priority"/>
         <label uri="rdf:*" class="rdf:http://www.example.com/rdf/name"/>

For the external rules, you could add another tag or attribute inside the rule that refers to other content.

Really, though, a more useful example needs to used, one that implements something that someone would want to do. For instance, display a newsfeed or a list of books.

PawelChmielowski: I'm working on template system with syntax similar to XSLT, and this is quite nice. Here http://jabberzilla.jabberstudio.org/trash/templates/test.xml is "live" demo to this.

DanBri: Heads up, you folks might like to keep an eye on the work of the W3C RDF Data Access Working Group. They are working on standard RDF query language (and protocol) based on a matching/binding model that is very close to the one used in Mozilla Templates. See the site for use-cases and (I hope soon) a Working Draft. The group operates in public view, and since the Mozilla Organization is a W3C Member now, there is possibility for direct participation. Feel free to contact me at danbri@w3.org about this. The WG is also likely to produce a simple XML format for query bindings, so that XSLT or XQuery could be used to format the results of a query (eg. into HTML, SVG, XUL etc). I believe there is potential for this to be a drop-in replacement for XUL Templates which would make good use of Mozilla's existing investment in both XSLT and RDF. Note that the design work is (as I write) still in progress, so it'd be a good time to get involved. RDF query is simple enough that I'm sure there will be many implementations of this language, including server-side stuff, so I'd strongly encourage Mozilla hackers to take an interest. Give me a shout if I can help...

PeterWilson: Re DanBri's coments about DAWG, I've just published a first version of a Javascript implementation of a SPARQL Query Engine. http://xulapp.mozdev.org/installation.html



I agree with Neil that templating and databinding are extemely similar. I think they can be treated as the same thing. In fact, databinding through templates allows super simple manipulation of the presentation DOM. (e.g. A list can become a textbox if the content warrants.)


I think content generation is completely distinct from templates. Templates would be associated with datasources, but not involved in the population of the datasources.

Datasources could be associated with a webservice/rdf/xml uri, via a an href attribute. If so, they could be populated when the parent document is opened. Thay could be (re-)populated later by event-triggered js. In this way they would be treated like an iframe or similar. They could be contained within a <datasource id="" href="".../> tag, but it might also be handy to be able to statically define the contents of any frament as a datasource with a "ds-id" (or whatever) attribute.

A template should not control the population of an existing datasource. A template could, however, create a new datasource, but only in the same way that it can create other document fragments (including iframes or other templates).

I don't think it is unreasonable to require the contents of a datasource to be XML. RDF is already XML, of course. The results of SQL queries can be trivially represented in XML. In cases where a datasource is linked to a web service uri, the service should be expected to return results in XML.


I admit some ignorance here on the wide world of options, but xsl seems like an obvious fit to me. It has the huge benefits from being an established open standard. It works for XML content (including SQL query results). The RDF club will point out it's shortcomings for handling RDF content.

I'm not an RDF guru, but couldn't you tweak xsl to allow an RDF expression anywhere an XPath expression is allowed? I imagine that adding an arc axis, etc. to XPath expressions wouldn't get anybody excited? I know that these are simple-minded, incredibly ignorant, and insensitive questions. They would also constitute "extentions" which could dilute many of the benefits cited earlier from using an established open standard. But it seems like a huge win to be able to leverage xsl(t). Feel free to correct my RDF ignorance or ignore it as absurd and uneducated.