Lists

From RDFa Working Group Wiki
Jump to: navigation, search

DOM Transformation using @collection and @member

The user view

Processing lists is triggered by a separate attribute @collection. Ie, the following code:

 <span rel="..." collection>
    ...
 </span>

triggers collection processing, as described below, on the subtree. The current subject in the subtree is usually a newly created blank node used as the head of the (RDF) list (unless there is a @resource or @href to set the resource). (Note the examples use the HTML5 syntax; in XHTML the attribute should be collection="whatever", ie, the value of the attribute is ignored.)

Collection processing means that the RDFa processor locates in the subtree, depth-first, any element with another special attribute called @member. The depth first search is stopped at the element with @member or if an element contains another @collection attribute value (this latter indeed signals another list).

When hitting an element with @member, but without @href or @resource, member behaves, conceptually, as a property="rdf:first" predicate, and any possible @property predicate on the element will be disregarded. If the element contains a @href or @resource, then member behaves, conceptually, as a rel="rdf:first" predicate, and possible @rel predicate on the element will be disregarded. In both cases, the additional triples to bind the list elements together via rdf:next are also added automatically to the processor graph.

The code below is a typical example:

 <li about="http://www.worldcatlibraries.org/isbn/9780262912423" typeof="bibo:Book">
   <span rel="dc:creator" collection>
     <span member>Grigoris Antoniou</span> and
     <span member>Frank van Harmelen</span>
   </span>
</li>

which yields:

<http://www.worldcatlibraries.org/isbn/9780262912423> a bibo:Book ;
     dc:creator ( "Grigoris Antoniou" "Frank van Harmelen" ) .

Or:

 <li about="http://www.worldcatlibraries.org/isbn/9780262912423" typeof="bibo:Book">
   <span rel="dc:creator" collection>
     <span member>Grigoris Antoniou</span> and
     <span class="link-style"><a member href="http://www.cs.vu.nl/~frankh/foaf.rdf">Frank van Harmelen</a></span>
   </span>
</li>

yielding:

<http://www.worldcatlibraries.org/isbn/9780262912423> a bibo:Book ;
     dc:creator ( "Grigoris Antoniou" <http://www.cs.vu.nl/~frankh/foaf.rdf> ) .

The specification view

Handling of collections does not change the core processing model. Instead, management of collections is defined via a (conceptual) pre-processing step on the DOM tree of the RDFa source: nodes in the DOM tree are modified (more specifically, attributes values are modified) and some new elements are added to the DOM tree for the creation of new triples. All modifications of the DOM tree are such that, once the DOM tree is modified, the normal RDFa Core processing steps can be executed to generate the necessary collection or container triples.

Collection transformation of the DOM

In what follows the term "new bnode id is generated" means that a string of the form "_:xxx" is created that is distinct from all other similarly formatted strings, whether appearing in the original RDFa source or as a result of an earlier, similar steps of generating a new bnode id in a collection transformation.

The modification of the DOM tree is made starting from the top element. The steps below are executed on all element nodes of the DOM tree as follows.

  1. If the node does not include the @collection attribute, processing on that node stops.
  2. If the node includes the @collection attribute then:
    1. if the node contains a @href or @resource attribute then this is the list id;
    2. if the node does not contain a @href or @resource then a new bnode id is generated as a list id, the attribute resource="‘list id’" is added to the element
    3. an array of bnode id-s is created and the newly generated list id is added to the tail of the array
    4. the DOM subtree starting at the node is traversed depth-first; for each descendent node:
      1. if the descendent node contains the @member attribute:
        1. if the node has no @href or @resourse then the attribute property="http://www.w3.org/1999/02/22-rdf-syntax-ns#first is added to the node (possibly overriding an existing @property value
        2. if the node has a @href or @resource then the attribute rel="http://www.w3.org/1999/02/22-rdf-syntax-ns#first is added to the node (possibly overriding an existing @rel value
        3. the attribute @about is set on the descendent node with the value set to the tail element of the array of bnode id-s (possibly overriding an existing @about attribute)
        4. a new bnode id is generated and its value is added to the tail of the array
        5. the traversal stops
      2. if the descendent node contains the @collection attribute, traversal stops
      3. otherwise, traversal is continued until the leaf nodes are reached
    5. Once the traversal is done, the array of bnode id-s is traversed from start to tail and, for each id a new child element is added to the node with
      1. the @about attribute set to the current bnode id of the array
      2. the @rel attribute set to http://www.w3.org/1999/02/22-rdf-syntax-ns#rest
      3. the @resource attribute set to the next bnode id of the array if applicable; if not, the value is set to http://www.w3.org/1999/02/22-rdf-syntax-ns#nil

Note: it is not specified what element is added to the node in step 2.5; these elements in the DOM tree are ephemeral and the implementation is free to use any element name.

Note: this specification describes the conceptual transformation of the DOM tree; implementation are not required to implement collections and containers exactly in these terms. They can, for example, fold these steps directly into the core processing steps.

Transformation Example

The following code shows what serialized form of the transformed DOM tree for the first example. The names of the elements added to the DOM, and their exact position, may differ from one implementation to the other.

<li about="http://www.worldcatlibraries.org/isbn/9780262912423" typeof="bibo:Book">
  <span rel="dc:creator" resource="_:xyz10">
   <span about="_:xyz10" property="http://www.w3.org/1999/02/22-rdf-syntax-ns#first">Grigoris Antoniou</span> and
   <span about="_:xyz11" property="http://www.w3.org/1999/02/22-rdf-syntax-ns#first">Frank van Harmelen</span>
   <list_links about="_:xyz10" rel="http://www.w3.org/1999/02/22-rdf-syntax-ns#rest" resource="_:xyz11"/>
   <list_links about="_:xyz11" rel="http://www.w3.org/1999/02/22-rdf-syntax-ns#rest" resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
  </span>
</li>

Possible questions

Why not reusing the HTML constructs like <ul/>?

First of all, these elements are HTML specific, and RDFa is defined for any XML dialects. But even in HTML it might become a restriction. Indeed, the sentence in the example should look on the screen as follows:

A Semantic Web Primer, by Grigoris Antoniou and Frank van Harmelen

instead of a bulleted list. It is of course possible to define CSS rules to generate the same visual effects for <ul> but those CSS rules are not obvious, are rarely used and most of the HTML authors are not familiar with them. On the other hand, adding the necessary attributes to list elements is not a huge load on the author…

Is it implementable?

Yes, Ivan has done it:-)

What about containers (Seq, Alt, Bag)

From the specification point of view it could be added by considering the value of @collection as significant. Ie, one could use collection="Seq" to generate a sequence. (The only caveat is that, instead of collection, some other attribute name should be used to avoid confusion with the terms as used in the RDF Semantics document.) The transformation rules are different, though simpler: there is no need for the extra ephemeral nodes and the rdf:_1, rdf:_2, etc, values should be used instead of rdf:first.

It is to be decided by the WG whether it is worth complicating the implementation with containers, which are not that useful in practice anyway.

Open Issues

How should this appear on the RDF API level?

The question is whether the API should reflect, shall we say, the original DOM or the transformed DOM when, e.g., creating Property groups? If the mechanism is defined as a preprocessing step, then it might be o.k. to stick to the transformed DOM (similarly to the fact that, if some syntax is used for lists in, say, Turtle, the triple store still contains the rdf:first, rdf:next, etc, predicates).

Processing Rules addition with @member alternative

An alternative implementation, using the @member attribute without the use of @collection. The advantage of this is that it removes a layer of required markup. This version eliminates @collection as being overly complicated. For example:

 <span rel="..." member>
    ...
 </span>

triggers collection processing, as described below, on the element or sub-tree. The an RDF list is associated with each of the predicate IRIs in @rel or @property. (Note the examples use the HTML5 syntax; in XHTML the attribute should be collection="whatever", ie, the value of the attribute is ignored.)

Collection processing means that the RDFa processor locates in the sub-tree starting from a subject definition, any element with another special attribute called @member. The depth first search is stopped at the element with @member.

Processing rules add a collection mappings to the Evaluation Context, which associates predicate IRIs with a memory array of sequential collection members. These members are serialized into an RDF List (using rdf:first/rdf:rest properties) which processing returns to the element where the collection mapping is defined.

The code below is a typical example:

<li about="http://www.worldcatlibraries.org/isbn/9780262912423" typeof="bibo:Book">
  <span property="dc:creator" member>Grigorius Antoniou</span>
  <span property="dc:creator" member>Frank van Harmelen</span>
</li>

which yields:

<http://www.worldcatlibraries.org/isbn/9780262912423> a bibo:Book ;
     dc:creator ( "Grigoris Antoniou" "Frank van Harmelen" ) .

Or:

<li about="http://www.worldcatlibraries.org/isbn/9780262912423" typeof="bibo:Book">
  <span property="dc:creator" member>Grigoris Antoniou</span> and
  <span rel="dc:creator" class="link-style">
    <a href="http://www.cs.vu.nl/~frankh/foaf.rdf">Frank van Harmelen</a>
  </span>
</li>

yielding:

<http://www.worldcatlibraries.org/isbn/9780262912423> a bibo:Book ;
     dc:creator ( "Grigoris Antoniou" <http://www.cs.vu.nl/~frankh/foaf.rdf> ) .

The specification view

Collections are implemented with simple additions to the processing model. The following describes updates to the specification including specific processing steps:

5. Attributes and Syntax

@member
an attribute (value ignored) used to indicate that the object associated with a @rel or @property attribute on the same element is to be added to the collection for that property. Causes a collection to be created if it does not already exist.

7.2 Evaluation Context

The collection mappings, a mapping from IRIs to collections.

7.5 step 1

add to local values:

** the collection mappings is set to the collection mappings from the evaluation context.

7.5 step 7

If the new subject is set and is not the same as parent object, replace the collection mappings taken from the evaluation context with a new empty mappings.

7.5 step 8

* If present, @rel may contain one or more IRIs, ...
** If the current element also has a @member attribute:
*** If the local collection mappings does not contain a collection associated with this IRI, instantiate a new collection and add to local collection mappings.
*** add the current object resource to the collection associated with that IRI in the local collection mappings
** Otherwise the current object resource is used to generate tripes as follows: ...

7.5 step 9

* If present, @rel must contain one or more IRIs, obtained according to the section on CURIE and IRI Processing. For each IRI:
** If the element has a @member attribute:
*** If the local collection mappings does not contain a collection associated with this IRI, instantiate a new collection and add to local collection mappings.
*** add an entry to the local list of incomplete triples as follows:
 ; collection
 : The collection from local collection mappings associated with this IRI.
** Otherwise, add an entry as follows:
 ; predicate
 : full IRI
 ; direction
 : forward

7.5 step 10

If the current element has a @member attribute, the current object literal is added to a collection associated with that IRI in the local collection mappings, otherwise the value is used to generate tripes as follows: ...

7.5 step 11

* If collection is set, add new subject to the collection. Otherwise, ...

7.5 step 12

* the 'collection mappings is set to the value of the local collection mappings.

7.5 step 13

Note, this is a new step, required as collection processing can't be completed until child elements have been processed.

After traversing through child elements, for each IRI and collection in the local collections mapping, if the equivalent collection does not exist in the evaluation context:
#Generate an rdf:List using elements from the collection (processing details basically the same as for Turtle or RDF/XML to be detailed later). (Note, this process does not produce empty lists, that must be done explicitly using rdf:nil).
#Generate a triple with new subject, IRI and the BNode identifying the collection.

Examples

Empty List: <> rdf:value () .

<div about ="">
  <p rel="rdf:value" resource="rdf:nil"/>
</div>

List with mixed IRI/Literal elements: <> rdf:value ("Foo" <foo>) .

<div about ="">
  <p property="rdf:value" member="">Foo</p>
  <a rel="rdf:value" member="" href="foo">Foo</p>
</div>

List with properties at different levels: <> rdf:value ("Foo" "Bar") .

<div about ="">
  <p property="rdf:value" member="">Foo</p>
  <strong><p property="rdf:value" member="">Bar</p></strong>
</div>

List with rel sub-tree: <> rdf:value (<foo> <bar>) .

<div about ="">
  <ol rel="rdf:value" member="">
    <li><a href="foo">Foo</a></li>
    <li><a href="bar">Bar</a></li>
  </ol
</div>

Property with list and literal: <> rdf:value ("Foo" "Bar"), "Baz" .

<div about ="">
  <p property="rdf:value" member="">Foo</p>
  <strong><p property="rdf:value" member="">Bar</p></strong>
  <p property="rdf:value">Baz</p>
</div>

Two lists: <foo> rdf:value ("Foo"), ("Bar") .

<div>
  <div about ="foo">
    <p property="rdf:value" member="">Foo</p>
  </div>
  <div about="foo">
    <p property="rdf:value" member="">Bar</p>
  </div>
</div>