This is a snapshot of an early working draft and has therefore been superseded by the HTML standard.

This document will not be further updated.

HTML 5

Call For Comments — 27 October 2007

3.19. Data Templates

3.19.1. Introduction

...examples...

3.19.2. The datatemplate element

Block-level element and metadata element.

Contexts in which this element may be used:
As the root element of an XML document.
Where metadata elements are expected.
Where block-level elements are expected.
Content model:
Zero or more rule elements.
Element-specific attributes:
None.
DOM interface:
No difference from HTMLElement.

The datatemplate element brings together the various rules that form a data template. The element doesn't itself do anything exciting.

3.19.3. The rule element

Contexts in which this element may be used:
As a child of a datatemplate element.
Content model:
Anything, regardless of the children's required contexts (but see prose).
Element-specific attributes:
condition
mode
DOM interface:
interface HTMLRuleElement : HTMLElement {
           attribute DOMString condition;
           attribute DOMString mode;
  readonly attribute DOMTokenString modeList;
};

The rule element represents a template of content that is to be used for elements when updating an element's generated content.

The condition attribute, if specified, must contain a valid selector. It specifies which nodes in the data tree will have the condition's template applied. [SELECTORS]

If the condition attribute is not specified, then the condition applies to all elements, text nodes, CDATA nodes, and processing instructions.

The mode attribute, if specified, must have a value that is an unordered set of space-separated tokens representing the various modes for which the rule applies. When, and only when, the mode attribute is omitted, the rule applies if and only if the mode is the empty string. A mode is invoked by the nest element; for the first node (the root node) of the data tree, the mode is the empty string.

The contents of rule elements form a template, and may be anything that, when the parent datatemplate is applied to some conforming data, results in a conforming DOM tree.

The condition DOM attribute must reflect the condition content attribute.

The mode and modeList DOM attributes must reflect the mode content attribute.

3.19.4. The nest element

Contexts in which this element may be used:
As a descendant of a rule element, regardless of the parent element's content model.
Content model:
Empty.
Element-specific attributes:
filter
mode
DOM interface:
interface HTMLNestElement : HTMLElement {
           attribute DOMString filter;
           attribute DOMString mode;
};

The nest element represents a point in a template where the user agent should recurse and start inserting the children of the data node that matches the rule in which the nest element finds itself.

The filter attribute, if specified, must contain a valid selector. It specifies which of the child nodes in the data tree will be examined for further processing at this point. [SELECTORS]

If the filter attribute is not specified, then all elements, text nodes, CDATA nodes, and processing instructions are processed.

The mode attribute, if specified, must have a value that is a word token consisting of one or more characters, none of which are space characters. It gives the mode which will be in effect when looking at the rules in the data template.

The filter DOM attribute must reflect the filter content attribute.

The mode DOM attribute must reflect the mode content attribute.

3.19.5. Global attributes for data templates

The template attribute may be added to an element to indicate that the template processing model is to be applied to that element.

The template attribute, when specified, must be a URI to an XML or HTML document, or a fragment identifier pointing at another part of the document. If there is a fragment identifier present, then the element with that ID in the target document must be a datatemplate element, otherwise, the root element must be a datatemplate element.

The template DOM attribute must reflect the template content attribute.

The ref attribute may be specified on any element on which the template attribute is specified. If it is specified, it must be a URI to an XML or HTML document, or a fragment identifier pointing at another part of the document.

When an element has a template attribute but no ref attribute, the element may, instead of its usual content model, have a single element of any kind. That element is then used as the root node of the data for the template.

The ref DOM attribute must reflect the ref content attribute.

The registrationmark attribute may be specified on any element that is a descendant of a rule element, except nest elements. Its value may be any string, including the empty string (which is the value that is assumed if the attribute is omitted). This attribute performs a role similar to registration marks in printing presses: when the generated content is regenerated, elements with the same registrationmark are lined up. This allows the author to disambiguate how elements should be moved around when generated content is regenerated in the face of changes to the data tree.

The registrationMark DOM attribute must reflect the registrationmark content attribute.

3.19.6. Processing model

3.19.6.1. The originalContent DOM attribute

The originalContent is set to a DocumentFragment to hold the original children of an element that has been replaced by content generated for a data template. Initially, it must be null. Its value is set when the template attribute is set to a usable value, and is unset when the attribute is removed.

The originalContent DOM attribute can thus be used as an indicator of whether a template is currently being applied, just as the templateElement DOM attribute can.

3.19.6.2. The template attribute

Setting: When an HTML element without a template attribute has its template attribute set, the user agent must fetch the specified file and parse it (without a browsing context, and with scripting disabled) to obtain a DOM. If the URI is the same as the URI of the current document, then the current document's DOM must be assumed to be that parsed DOM. While this loading and parsing is in progress, the element is said to be busy loading the template rules or data.

If the resource specified by the template attribute is not the current document and does not have an XML MIME type, or if an XML parse error is found while parsing the resource, then the resource cannot be successfully parsed, and the user agent must jump to the failed to parse steps below.

Once the DOM in question has been parsed, assuming that it indeed can be parsed and does so successfully, the user agent must wait for no scripts to be executing, and as soon as that opportunity arises, run the following algorithm:

  1. If the template attribute's value has a fragment identifier, and, in the DOM in question, it identifies a datatemplate element, then set the templateElement DOM attribute to that element.

    Otherwise, if the template attribute value does not have a fragment identifier, and the root element of the DOM in question is a datatemplate element, then set the templateElement DOM attribute to that element.

    Otherwise, jump to the failed to parse steps below.

  2. Create a new DocumentFragment and move all the nodes that are children of the element to that DocumentFragment object. Set the originalContent DOM attribute on the element to this new DocumentFragment object.

  3. Jump to the steps below for updating the generated content.

If the resource has failed to parse, the user agent must fire a simple event with the name error at the element on which the template attribute was found.

Unsetting: When an HTML element with a template attribute has its template attribute removed or dynamically changed from one value to another, the user agent must run the following algorithm:

  1. Set the templateElement DOM attribute to null.

  2. If the originalContent DOM attribute of the element is not null, run these substeps:

    1. Remove all the nodes that are children of the element.

    2. Append the nodes in the originalContent DocumentFragment to the element.

    3. Set originalContent to null.

    (If the originalContent DOM attribute of the element is null, then either there was an error loading or parsing the previous template, or the previous template never finished loading; in either case, there is nothing to undo.)

  3. If the template attribute was changed (as opposed to simply removed), then act as if it was now set to its new value (fetching the specified page, etc, as described above).

The templateElement DOM attribute is updated by the above algorithm to point to the currently active datatemplate element. Initially, the attribute must have the value null.

3.19.6.3. The ref attribute

Setting: When an HTML element without a ref attribute has its ref attribute set, the user agent must fetch the specified file and parse it (without a browsing context, and with scripting disabled) to obtain a DOM. If the URI is the same as the URI of the current document, then the current document's DOM is assumed to be that parsed DOM. While this loading and parsing is in progress, the element is said to be busy loading the template rules or data.

If the resource specified by the ref attribute is not the current document and does not have an XML MIME type, or if an XML parse error is found while parsing the resource, then the resource cannot be successfully parsed, and the user agent must jump to the failed to parse steps below.

Once the DOM in question has been parsed, assuming that it indeed can be parsed and does so successfully, the user agent must wait for no scripts to be executing, and as soon as that opportunity arises, run the following algorithm:

  1. If the ref attribute value does not have a fragment identifier, then set the refNode DOM attribute to the Document node of that DOM.

    Otherwise, if the ref attribute's value has a fragment identifier, and, in the DOM in question, that fragment identifier identifies an element, then set the refNode DOM attribute to that element.

    Otherwise, jump to the failed to parse steps below.

  2. Jump to the steps below for updating the generated content.

If the resource has failed to parse, the user agent must fire a simple event with the name error at the element on which the ref attribute was found, and must then jump to the steps below for updating the generated content (the contents of the element will be used instead of the specified resource).

Unsetting: When an HTML element with a ref attribute has its ref attribute removed or dynamically changed from one value to another, the user agent must run the following algorithm:

  1. Set the refNode DOM attribute to null.

  2. If the ref attribute was changed (as opposed to simply removed), then act as if it was now set to its new value (fetching the specified page, etc, as described above). Otherwise, jump to the steps below for updating the generated content.

The refNode DOM attribute is updated by the above algorithm to point to the current data tree, if one is specified explicitly. If it is null, then the data tree is given by the originalContent DOM attribute, unless that is also null, in which case no template is currently being applied. Initially, the attribute must have the value null.

3.19.6.4. The NodeDataTemplate interface

All objects that implement the Node interface must also implement the NodeDataTemplate interface, whose members must be accessible using binding-specific casting mechanisms.

interface NodeDataTemplate {
  readonly attribute Node dataNode;
};

The dataNode DOM attribute returns the node for which this node was generated. It must initially be null. It is set on the nodes that form the content generated during the algorithm for updating the generated content of elements that are using the data template feature.

3.19.6.5. Mutations

An element with a non-null templateElement is said to be a data tree user of the node identified by the element's refNode attribute, as well as all of that node's children, or, if that attribute is null, of the node identified by the element's originalContent, as well as all that node's children.

Nodes that have one or more data tree users associated with them (as per the previous paragraph) are themselves termed data tree component nodes.

Whenever a data tree component node changes its name or value, or has one of its attributes change name or value, or has an attribute added or removed, or has a child added or removed, the user agent must update the generated content of all of that node's data tree users.

An element with a non-null templateElement is also said to be a template tree user of the node identified by the element's templateElement attribute, as well as all of that node's children.

Nodes that have one or more template tree users associated with them (as per the previous paragraph) are themselves termed template tree component nodes.

Whenever a template tree component node changes its name or value, or has one of its attributes change name or value, or has an attribute added or removed, or has a child added or removed, the user agent must update the generated content of all of that node's template tree users.

In other words, user agents update the content generated from a template whenever either the backing data changes or the template itself changes.

3.19.6.6. Updating the generated content

When the user agent is to update the generated content of an element that uses a template, the user agent must run the following steps:

  1. Let destination be the element whose generated content is being updated.

  2. If the destination element is busy loading the template rules or data, then abort these steps. Either the steps will be invoked again once the loading has completed, or the loading will fail and the generated content will be removed at that point.

  3. Let template tree be the element given by destination's templateElement DOM attribute. If it is null, then abort these steps. There are no rules to apply.

  4. Let data tree be the node given by destination's refNode DOM attribute. If it is null, then let data tree be the node given by the originalContent DOM node.

  5. Let existing nodes be a set of ordered lists of nodes, each list being identified by a tuple consisting of a node, a node type and name, and a registration mark (a string).

  6. For each node node that is a descendant of destination, if any, add node to the list identified by the tuple given by: node's dataNode DOM attribute; the node's node type and, if it's an element, its qualified name (that is, its namespace and local name), or, if it's a processing instruction, its target name, and the value of the node's registrationmark attribute, if it has one, or the empty string otherwise.

  7. Remove all the child nodes of destination, so that its child node list is empty.

  8. Run the Levenberg data node algorithm (described below) using destination as the destination node, data tree as the source node, template tree as the rule container, the empty string as the mode, and the existing nodes lists as the lists of existing nodes.

The Levenberg algorithm consists of two algorithms that invoke each other recursively, the Levenberg data node algorithm and the Levenberg template node algorithm. These algorithms use the data structures initialised by the set of steps described above.

The Levenberg data node algorithm is as follows. It is always invoked with three DOM nodes, one string, and a set of lists as arguments: the destination node, the source node, the rule container, the mode string, and the existing nodes lists respectively.

  1. Let condition be the first rule element child of the rule container element, or null if there aren't any.

  2. If condition is null, follow these substeps:

    1. If the source node is an element, then, for each child child node of the source node element, in tree order, invoke the Levenberg data node algorithm recursively, with destination node, child node, rule container, the empty string, and existing nodes lists as the five arguments respectively.

    2. Abort the current instance of the Levenberg data node algorithm, returning to whatever algorithm invoked it.

  3. Let matches be a boolean with the value true.

  4. If the condition element has a mode attribute, but the value of that attribute is not a mode match for the current mode string, then let matches be false.

  5. If the condition element has a condition attribute, and the attribute's value, when evaluated as a selector, does not match the current source node, then let matches be false.

  6. If matches is true, then follow these substeps:

    1. For each child child node of the condition element, in tree order, invoke the Levenberg template node algorithm recursively, with the five arguments being destination node, source node, rule container, child node, and existing nodes lists respectively.

    2. Abort the current instance of the Levenberg data node algorithm, returning to whatever algorithm invoked it.

  7. Let condition be the next rule element that is a child of the rule container element, after the condition element itself, or null if there are no more rule elements.

  8. Jump to step 2 in this set of steps.

The Levenberg template node algorithm is as follows. It is always invoked with four DOM nodes and a set of lists as arguments: the destination node, the source node, the rule container, the template node, and the existing nodes lists respectively.

  1. If template node is a comment node, abort the current instance of the Levenberg template node algorithm, returning to whatever algorithm invoked it.

  2. If template node is a nest element, then run these substeps:

    1. If source node is not an element, then abort the current instance of the Levenberg template node algorithm, returning to whatever algorithm invoked it.

    2. If the template node has a mode attribute, then let mode be the value of that attribute; otherwise, let mode be the empty string.

    3. Let child node be the first child of the source node element, or null if source node has no children.

    4. If child node is null, abort the current instance of the Levenberg template node algorithm, returning to whatever algorithm invoked it.

    5. If the template node element has a filter attribute, and the attribute's value, when evaluated as a selector, matches child node, then invoke the Levenberg data node algorithm recursively, with destination node, child node, rule container, mode, and existing nodes lists as the five arguments respectively.

    6. Let child node be child node's next sibling, or null if child node was the last node of source node.

    7. Return to step 4 in this set of substeps.

  3. If template node is an element, and that element has a registrationmark attribute, then let registration mark have the value of that attribute. Otherwise, let registration mark be the empty string.

  4. If there is a list in the existing nodes lists corresponding to the tuple (source node, the node type and name of template node, registration mark), and that list is not empty, then run the following substeps. (For an element node, the name of the node is its qualified tag name, i.e. its namespace and local name. For a processing instruction, its name is the target. For other types of nodes, there is no name.)

    1. Let new node be the first node in that list.

    2. Remove new node from that list.

    3. If new node is an element, remove all the child nodes of new node, so that its child node list is empty.

    Otherwise, if there is no matching list, or there was, but it is now empty, then run these steps instead:

    1. Let new node be a shallow clone of template node.

    2. Let new node's dataNode DOM attribute be source node.

  5. If new node is an element, run these substeps:

    1. For each attribute on new node, if an attribute with the same qualified name is not present on template node, remove that attribute.

    2. For each attribute attribute on template node, run these substeps:

      1. Let expanded be the result of passing the value of attribute to the text expansion algorithm for templates along with source node.

      2. If an attribute with the same qualified name as attribute is already present on new node, then: if its value is different from expanded, replace its value with expanded.

      3. Otherwise, if there is no attribute with the same qualified name as attribute on new node, then add an attribute with the same namespace, prefix, and local name as attribute, with its value set to expanded's.

    Otherwise, the new node is a text node, CDATA block, or PI. Run these substeps instead:

    1. Let expanded be the result of passing the node value of template node (the content of the text node, CDATA block, or PI) to the text expansion algorithm for templates along with source node.

    2. If the value of the new node is different from expanded, then set the value of new node to expanded.

  6. Append new node to destination.

  7. If template node is an element, then, for each child child node of the template node element, in tree order, invoke the Levenberg template node algorithm recursively, with the five arguments being new child, source node, rule container, child node, and existing nodes lists respectively.

Define: evaluated as a selector

Define: text expansion algorithm for templates