INRIA
[Up]
Warning

Work in progress

This version may be updated without notice.

XCL Specification

The XML Control Language

Working Draft 03 november 2007

Editor
Philippe Poulard  <Philippe · Poulard [at] sophia · inria · fr>

Copyright © INRIA

Abstract

XCL is one of the core modules of the Active Tags technology.

XCL provides a set of tags that covers many useful features :

This module is just a convenient toolkit that covers most of useful general-purpose features, but does not intend to cover specific processes. Users should define their own module with EXP when they have to use made-to-measure dedicated processes.

Requirement levels

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Note that for reasons of style, these words are not capitalized in this document.

Active Tags specifications

The following specifications are part of the Active Tags technologies.

Table of contents

1 Control structure actions

1.1 Controling execution
1.2 Assigning datas
1.3 Organizing processes
1.4 Sorting
2 XML oriented actions
2.1 Dealing with SAX and DOM
3 Active Update
4 Filtering
4.1 Connecting filters
4.2 Rules
4.3 Channels
4.4 Filter definitions
4.5 Built-in filters
5 Fallback processing and definition
6 XCL module reference
6.1 Elements
6.2 Foreign attributes
6.3 Predefined properties
6.4 Extended XPath functions
6.5 Data types

Appendix

A Glossary
B Related Active Tags specifications
C Lists

C.1 Examples list
D Active Schema for XCL


1 Control structure actions

XCL provides instructions common to most imperative language to control the execution, assign datas, or organize processes.

1.1 Controling execution

As in many languages, XCL provides instructions to perform tests and loops :

1.2 Assigning datas

Many active tags cause the creation of a property in the data set. Usually, the @name attribute specifies the name of the property to create ; if missing, the property is set as the current object.

Such active tags are, for example :

The active tags above are also performing tasks to accomplish what they are intending for. To simply assign a value to a property without performing additional tasks, XCL provides the <xcl:set> element. <xcl:set> can be used for simple assignment as well as for computations, for object browsing with XPath, or for building lists, maps, XML fragments, or even a mix of these structures.

Assignment of simple values

The <xcl:set> element may host the @value attribute to perform simple assignments :

    <xcl:set name="who" value="Bill"/>
    <xcl:set name="welcome" value="Hello { $who } !"/>

To create new properties in the data set...

    <xcl:set value="Bill"/>
    <xcl:set value="Hello { . } !"/>

...to set a new value to the current object.

XPath can be used to perform computations :

    <xcl:set name="pi" value="{ number( '3.1415' ) }"/>
    <xcl:set name="total" value="{ $price * $qty }"/>
    <xcl:set name="files" value="{ count( $files ) }"/>

... to cross XML nodes :

    <xcl:set name="total" value="{ orders/order[ @confirmed ]/@total }"/>

... to cross X-operable objects :

    <xcl:set name="files" value="{ io:file( '/path/to/dir' )//*[@io:is-file] }"/>

Assignment of composite values

In Active Tags, a composite value consists on a collection of named or unamed items. When the @value attribute of the <xcl:set> element is omitted, each item may be specified within the content with the <xcl:item> element. The <xcl:item> may have itself a @value and a @name attributes.

In fact, if the @value attribute is not specified in the <xcl:set> or in the <xcl:item> elements, the content is performed ; the items of the context are used as the values to set.

    <xcl:set name="who">
        <xcl:item name="firstname" value="John"/>
        <xcl:item name="lastname" value="Doe"/>
    </xcl:set>
    <xcl:set name="welcome" value="Hello { $who/firstname } { $who/lastname } !"/>
    <xcl:set name="tasks">
        <xcl:item value="open"/>
        <xcl:item value="remove"/>
    </xcl:set>
    <xcl:set name="todo" value="Before : { $tasks/*[1] } ; after : { $tasks/*[2] }"/>
    <xcl:set name="files">
        <xcl:item name="toDelete">
            <xcl:item value="{ io:file( '/path/to/file1' ) }"/>
            <xcl:item value="{ io:file( '/path/to/file2' ) }"/>
        </xcl:item>
        <xcl:item name="toCreate">
            <xcl:item value="{ io:file( '/path/to/file3' ) }"/>
            <xcl:item value="{ io:file( '/path/to/file4' ) }"/>
        </xcl:item>
    </xcl:set>

Instead of named or unamed items, the content may be a snippet XML structure :

    <xcl:set name="who">
        <firstname>John</firstname>
        <lastname>Doe</lastname>
    </xcl:set>
    <xcl:set name="welcome"
value="Hello { $who/firstname/text() } { $who/lastname/text() } !"/>

Items or other content may also be set conditionally :

    <xcl:set name="files">
        <xcl:item name="toDelete" xcl:if="{ $validate='yes' }">
            <xcl:item value="{ io:file( '/path/to/file1' ) }"/>
            <xcl:item value="{ io:file( '/path/to/file2' ) }"/>
        </xcl:item>
        <xcl:item name="toCreate">
            <xcl:item value="{ io:file( '/path/to/file3' ) }"/>
            <xcl:item value="{ io:file( '/path/to/file4' ) }"/>
        </xcl:item>
    </xcl:set>
    <xcl:set name="who">
        <xcl:if test="{ $gender='male' }">
            <xcl:then>
                <firstname>John</firstname>
            </xcl:then>
            <xcl:else>
                <firstname>Jane</firstname>
            </xcl:else>
        </xcl:if>
        <lastname>Doe</lastname>
    </xcl:set>
    <xcl:set name="welcome"
value="Hello { $who/firstname/text() } { $who/lastname/text() } !"/>

Scope

Most active tags that are creating a new property define also the @scope attribute that indicates which is the scope of the property to create. The values are shared, global, or local.

local is usually the default scope.

Parameters

Some active tags accept parameters to tune their behaviour. For this purpose, they open a context, run their subactions, and use each item found in the context as parameters. To set a parameter in the context, use the <xcl:param> element.

For example, a stylesheet may accept parameters :

<xcl:transform output="/path/to/doc.html" source="/path/to/doc.xml"
stylesheet="/path/to/stylesheet.xsl"> <xcl:param name="date" value="{ $date }"/> <xcl:param name="page" value="1"/> </xcl:transform>

For example, when storing a file to an XML Native Database through XML:DB, the type of the resource must be specified :

    <io:file name="myFile" uri="xmldb:provider://user:pwd@host:port/path/to/resource">
        <xcl:param name="xmldb-resource-type" value="XMLResource"/>
    </io:file>
    <io:save content="..." uri="{ $myFile }"/>

1.3 Organizing processes

The <xcl:active-sheet> element is usually the root element of an Active Sheet, but for specific purposes, some other elements are also suitable, such as <web:service> and <exp:module>. The root element of an Active Document may be any litteral element (that is to say an element that is not active).

Within an Active Sheet or an Active Document, the <xcl:logic> element may be used to organize callable unit processes ; its @name attribute defines the name of each logic procedure. Only one logic procedure may omit this attribute, which makes it the default. The Active Sheet (or Active Document) itself is designated as the main logic procedure.

To call a logic procedure, the <xcl:call> element can be used ; the data set inside the called logic procedure keeps the shared and global properties, but its local properties are empty, unless otherwise parameters are explicitely passed with the <xcl:param> element. At the end of the execution of the called procedure, the process goes on after the caller action. If local properties of the data set in use by the called logic procedure must be kept, each must be explicitely specify with the <xcl:keep> element. All other local properties are lost.

[TODO: an example]

1.4 Sorting

Sorting is a feature strongly related to types of data, when they required a total ordering on some set of objects. Active Tags covers many data-type issues in several specifications :

These methods always deal with typed data ; a data is always typed in Active Tags ; the default type is #xs:string. However, some objects are not necessary comparable with others, which makes sorting results somewhat hazardous. Comparable objects are sorted according to the comparator function bound to their type. Active Schema allow to specify which comparator function to bind to user define types, and also indicates how to compare 2 objects of different types ; this last points makes sorting a context-sensitive feature : 2 Active Tags applications might choose to bind different comparator functions to a type ; please refer to the chapter about "integration with EXP" for more information.

The type of a data is defined :

The xcl:sort() function allow to sort a list of items regarding one or more type-aware sorting criteria. The xcl:reverse() function can reverse the sorting order of each criterion (that is to say in descendant order). This function can also be used out of the context of the sort function ; in this case, it reverses the order of the items in a collection.

Sorting XML datas after infoset augmentation

In this example, a weather report indicates town temperatures expressed in °C as well as in °F. The type of the @temp attribute is those defined in another example.

<weather-report>
    <town date="2005/09/09" name="Paris" temp="21°C"/>
    <town date="2005/09/08" name="Paris" temp="22°C"/>
    <town date="2005/09/09" name="Vladivostok" temp="32°F"/>
    <town date="2005/09/07" name="Paris" temp="20°C"/>
    <town date="2005/09/08" name="London" temp="23°C"/>
</weather-report>

The following snippet code simply parses the XML file, and validate it with the schema within which the expected type is defined ; then the towns are displayed in temperature order thanks to the xcl:sort() function :

    <xcl:parse name="wr" source="file:///path/to/weather-report.xml"/>
    <asl:validate augment="yes" node="{ $wr }" schema="file:///path/to/schema.asl"/>
    <xcl:for-each name="town" select="{ xcl:sort( $wr/weather-report/town, @temp ) }">
        <xcl:echo value="{ $town/@temp } { $town/@name } { $town/@date }"/>
    </xcl:for-each>

Output :

32°F Vladivostok 2005/09/09
20°C Paris 2005/09/07
21°C Paris 2005/09/09
22°C Paris 2005/09/08
23°C London 2005/09/08

As expected, 32°F is placed before 20°C. If the @augment attribute of the <asl:validate> element was set to no, the temperatures will be sorted in lexical order, so 32°F would be placed at the last position. To force a lexical order on the augmented infoset, it is also possible to wrap the sort criterion with the string() function : string( @temp ).


2 XML oriented actions

Actions related to XML include :

Schema validation is provided while parsing with the @validate attribute of the <xcl:parse> element or with the <asl:validate> element.

[TODO]

2.1 Dealing with SAX and DOM

In most cases, Active Tags handles XML documents without specifying if the underlying API is DOM or SAX ; however, it may be advantageous to prefer one or the other technique in certain cases, in particular when performances are critical : SAX may be more suitable because it allow to connect components in a pipeline fashion. Moreover, DOM trees are fully accessible with XPath expressions, whereas SAX events are not suitable to XPath because in Active Tags XPath expressions are used both upon XML datas and non-XML datas compliant with XML, known as cross-operable objects. Thus, SAX documents may be preferred to DOM documents by applications that don't need to access to the content with XPath.

For example, Web applications built with pipelines serve dynamic pages faster, like shown in the example below :

3-tiers Web application with a SAX pipeline

In this example, the tiers involved are an XML native database, the Web front that hosts the Active Sheet below, and the browser, that will start to display the result whereas the XML native database still computes the request :

    <web:mapping match="..." method="GET">
        <io:request connect="xmldb:provider://user:pwd@host:port" name="results" output-type="SAX"
query="..." type="myQueryLanguage"/> <xcl:document name="allResults" type="SAX"> <!--merge each result in a single document--> <results> { $results } </results> </xcl:document> <xcl:transform output="{ $web:response/@web:output }" source="{ $allResults }"
stylesheet="results.xslt"/> </web:mapping>

We assume in this example that the XML native database will return several XML results that we want to merge and transform to a single HTML output.

  • <io:request> launches the request to the XML native database and create a property that represent the result that one start to handle without waiting the end of the request.
  • <xcl:document> indicates how to build a single XML document that merges all the results. As its type is SAX, it is deferred until a client component ask to consume its content ; here, the following <xcl:transform> element is this client.
  • <results> is not bound to an Active Tags module, it is a litteral to reproduce as is, like XSLT does. Within it, we simply insert the XML datas represented by the $results property : each XML document of the result will fire SAX events on behalf of the consumer component.
  • the last <xcl:transform> step will consume the document created to produce an HTML result ; in fact, it is the component that cause the real execution of the whole chain.

In fact, although Active Tags hides the API involved in most usage, processing SAX events is not exactly the same than processing DOM trees. As explained in the example above, SAX events are deferred actions : when an XML document is of the type SAX, it is not really created ; a SAX handler that represent it is available for the actions that follows, and may be used to be connected to a component that will consume the document ; the inner actions will be processed only when the document will be consumed. This makes the sequence of actions somewhat disrupted. Actions made for SAX processing can't be safely switched to actions that are dealing with DOM.

DOM or SAX ?

The following example show two snippet Active Sheets that are almost the same (they only differ by the @type attribute of the <xcl:document> element), but will produce two different XML documents :

  <xcl:set name="var" value="1"/>
  <xcl:document name="myXML" type="DOM">
      <root>
          <xcl:if test="{ $var = 1 }">
              <xcl:then>
                  <xcl:attribute name="foo" value="bar"/>
              </xcl:then>
          </xcl:if>
      </root>
  </xcl:document>
  <xcl:set name="var" value="0"/>
  <xcl:transform output="{ $sys:out }" source="{ $myXML }"/>

The process is performed in the tag order, producing the following result :

<root foo="bar"/>
  <xcl:set name="var" value="1"/>
  <xcl:document name="myXML" type="SAX">
      <root>
          <xcl:if test="{ $var = 1 }">
              <xcl:then>
                  <xcl:attribute name="foo" value="bar"/>
              </xcl:then>
          </xcl:if>
      </root>
  </xcl:document>
  <xcl:set name="var" value="0"/>
  <xcl:transform output="{ $sys:out }" source="{ $myXML }"/>

The tags inside the <xcl:document> element are not processed immediately ; they are deferred when the document is consumed by the <xcl:transform> element, but the $var has changed, and the attribute is not created :

<root/>

Moreover, the litteral elements that may appear within a SAX <xcl:document> are also deferred : that is to say that here again the sequence is disrupted to avoid caching all the datas when attribute definitions or namespace declarations are encountered, because even if they can be defined anywhere in the content of the litteral element, they have to be applied on it. Actually, the content of a litteral element is performed but not recursively for each other litteral elements encountered inside ; thus, the events will be fired once the content performed without forgetting attribute definitions neither namespace declarations. Nested litteral elements will be processed in the same way when corresponding events have to be fired. In a global view, the processing sequence is performed level by level instead of in tree order.

Of course, this also applies on elements produced with the <xcl:element> action.

[FIXME: I really don't know if it is the good strategy for processing SAX ; events could be fired as soon as the first content is encountered, next attributes encountered would be errors.]

Switching from SAX to DOM (and vice-versa)

Active Tags is based on XPath to access datas, and it is not obvious to use XPath with SAX when several XPath expressions are involved sequentially : how to get an element that has been already consumed by a previous action ? Using a DOM fragment feeds with SAX events may help significantly : DOM act as a data aggregator, as a container that retain the datas needed for XPath extractions.

The <xcl:document> element is useful for this purpose :

    <xcl:parse name="saxHandler" source="/path/to/my/file.xml" type="SAX"/>
    <!-- ... -->
    <xcl:document type="DOM">
        { $saxHandler }
    </xcl:document>

...but it may be used to fire SAX events from a DOM source :

    <xcl:parse name="domTree" source="/path/to/my/file.xml" type="DOM"/>
    <!-- ... -->
    <xcl:document type="SAX">
        { $domTree }
    </xcl:document>

Merging XML

In fact, any mix of SAX and DOM may be merged in a single SAX or DOM document. Moreover, the resulting XML may also contain custom elements :

    <xcl:parse name="saxHandler" source="/path/to/John-items.xml" type="SAX"/>
    <xcl:parse name="domTree" source="/path/to/customers.xml" type="DOM"/>
    <!-- ... -->
    <xcl:document type="SAX">
             <!-- type="DOM" works similarly -->
        <purchaseOrder>
            { $saxHandler }
            <billTo>
                { $domTree//customer[@name="John"] }
            </billTo>
        </purchaseOrder>
    </xcl:document>

XML fragments

<xcl:document> is also suitable when an XML source is not intend to produce a well-formed XML document with a single root element. For example, a data source may produce text data around the root element(s), which is forbidden in pure XML ; it is easy with Active Tags to complete such XML datas with a host root, giving a fully conformed XML document, as shown below :

    <xcl:parse name="xmlDatas" source="/path/to/my/file.xml"/>
    <!-- ... -->
    <xcl:document type="SAX">
             <!-- type="DOM" works similarly -->
        <root>
            { $xmlDatas }
        </root>
    </xcl:document>

The content of the file :

<?xml version="1.0" encoding="iso-8859-1"?>
Text before begin <begin>Hello world</begin> some text <end> </end> text after the end
[TODO]

3 Active Update

Active Update is a feature of Active Tags that allows to update XML objects and X-operable objects with a set of basic operations. XCL implements Active Update with a set of advanced operations, more convenient to use than basic operations.

Some operations denotes that the object referred (called the referent) is part of a collection for which ordering may be important, or not ; for example, XML elements are such objects. When specified, the referent may be an integer that denotes the position of the object referred within the collection it belongs. The first item in a collection is at the position 1.

Warning

Some objects may be hierarchically linked to another object that it depends, called its parent. It is itself one of its children. Some operations on such objects may require to specify explicitely the parent of the referent when it is involved, others don't need to.

When specified, an operand is needed to perform a specific operation.

If the referent computed at runtime gives nothing, the operation fails without trying to resolve other datas (parent, operand, and inner actions).

List of X-operations

In the list below, the referent, the parent and the operand (if any) are given respectively by the @referent, @parent, and @operand attributes. If an operand is expected and the @operand attribute is missing, the content of the X-operations will be performed ; when done, the operand will be the current object.

Warning

Notice that some operation act on the referent object itself (rename), others on its children (append), and other on the children of its parent (insert after).

The mapping between basic actions and the X-operations listed above is implied, according to the X-operable object and its characteristics :

An X-operation is only an XML way to apply basic Active Update actions.

Note

An X-operable objects, may define restrictions on basic operations.

Deferred operations

When used alone, an operation is applied when encountered at runtime. However, a set of operations may be grouped together in the aim of being applied or cancelled on user request. When this feature is used, the operations encountered are deferred operations. For this purpose, XCL provides the <xcl:commit> and <xcl:rollback> actions. The <xcl:operations> action is used to define the boundaries of a set of nested operations to defer.

A deferred operation must resolve its referent, parent and operand as soon as it is encountered. When applied, it must not resolve them again.

Note

This facility has been introduced to ease the usage of XUpdate-like operations on XML objects when incompatible updates are encountered : for example, if the first element of a node set must be removed and the second one must be updated, the expected result won't be obtained because once the first element will be removed, the second will become the first and the third the second ; this is the one that will be updated.

A set of deferred operations act like if the XML document were frozen during the updates operations that are really applied later.

If not specified, a set of deferred operations is applied automatically at the end of its execution.

Example

Example of X-operations

What would happened with XUpdate if the first entry was removed, and a new entry inserted after the second one ? The expected result won't be obtained !

XCL allows to perform safely such operations thanks to Active Update, like shown below :

<?xml version="1.0" encoding="iso-8859-1"?>
<xcl:operations deferred="yes" xcl:version="1.0" xmlns:xcl="http://ns.inria.org/active-tags/xcl"> <xcl:remove select="/addresses/address[1]"/> <xcl:insert-after select="/addresses/address[2]"> <xcl:if test="{ not(following-sibling::address/@id=3) }"> <address id="3"> <fullname>Philippe Poulard</fullname> <born day="10" month="06" year="1969"/> <town>Châteauneuf</town> <country>France</country> </address> </xcl:if> </xcl:insert-after> </xcl:operations>

The updates requested are performed when the closing tag </xcl:operations> is reached, because a deferred update was wanted (if commit or rollback orders are not encountered, updates operations are autocommited) ; thus, the updates are safely applied.


4 Filtering

XCL defines a set of tags for applying XPath-based filters on XML entries (DOM or SAX) and plain-text streams.

A filter reads entirely one or several inputs, and can produce several outputs. Unlike XSLT, an XCL filter traverses each input tree in its natural order only. More complex processes that require deep structure transformations should be considered with XSLT. XCL filters are suitable when processes are localized on independant chunks of datas, which is advantageous for stream-processing of large inputs, although XCL filters can be also convenient for traversing automatically a DOM tree. By combining other active tags with the small set defined here, it is yet possible to achieve efficient pipeline processes.

An XCL filter act on the XPath data model of the inputs, whatever the style of reading (events or tree). Thus, everything read is presented to the filter as an XML node. The results produced have the same infoset whatever the style of reading, except if side effects due to deferring process occurs, as shown previously. The nature of the output is the same as the input, except if it is explicitely changed by using actions such as <xcl:document> that can produce a tree or events at user option. When several inputs are merged to a single output, the first data forwarded to the output determine the nature of the output.

An XCL filter is defined thanks to the <xcl:filter> element, which contains a set of ordered rules (<xcl:rule>). Within a rule, it is possible :

According to the attributes used with, the <xcl:filter> element can be used :

A filter can be both an inline filter definition and be connected to an input. External filters can be parsed thanks to the <xcl:parse-filter> element, that can also parse built-in filters.

4.1 Connecting filters

Filters can be connected in a pipeline where the output of a filter becomes the input of a next filter. The first filter can be connected to an XML parser (or another XML producer), and the last to an XSLT transformer (or another XML consumer) :

    <xcl:parse name="input" output-type="event" source="file:///path/to/file.xml"/>
    <xcl:filter name="step1" source="{ $input }">
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:filter name="step2" source="{ $step1 }">
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:filter name="step3" source="{ $step2 }">
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:transform output="file:///path/to/result.xml" source="{ $step3 }"/>

...or "anonymously" :

    <xcl:parse output-type="event" source="file:///path/to/file.xml"/>
    <xcl:filter>
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:filter>
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:filter>
        <!--some rules to apply here-->
    </xcl:filter>
    <xcl:transform output="file:///path/to/result.xml"/>

Of course, XSLT transformers can also act as filters.

4.2 Rules

A filter appears as a set of ordered rules that can match nodes either on XPath patterns, or regular expressions. Once a rule matched, it is applied. A rule processes the node and its content separately : usually, the user act on the node before forwarding it to the next step, which cause the filter reading its content. A default rule is defined in order to match any node that weren't matched by the filter designed by the user :

    <xcl:filter name="..." source="...">
        <xcl:rule pattern="/ | node()">
            <xcl:forward>
                <xcl:apply-rules/>
            </xcl:forward>
        </xcl:rule>
    </xcl:filter>

This rule means that the node matched is forwarded as-is to the next step. Its content will be processed by the filter to look for a candidate rule. Thus, a minimal user-defined filter like this :

    <xcl:filter name="..." source="..."/>

...consist on reading its input and forward it as-is to the next step, because the only rule defined is the default rule which is appliable on each node of the input. The default rule is always the last rule applied if none matched, and users don't have to define this default rule. Designing a filter is easy because every node that is not explicitely matched is forwarded ; users just need to focus on what have to be changed while processing the pipeline.

The XPath patterns allowed in a rule definition are those defined in XSLT minus the key function which is dedicated to XSLT. According to the nature of the entry processed (DOM or SAX), they must be fully supported (case of DOM) or partially supported (case of SAX) by the underlying implementation. Actually, matching SAX events with XPath patterns may require to cache some datas expected to evaluate the pattern ; in order to keep the advantage of a streaming strategy, the cache must be as small as possible. A pattern that would require the entire entry to be cached would break the advantage of streaming, and a DOM-based strategy would be more suitable. Considering the pros and cons of caching capabilities, an implementation is free to restrict the usage of XPath patterns to a subset. Out of this subset, XPath patterns are considered unpredictable.

When a node matches a rule, the current object is set to the node that matched. When several rules are matching, those that has the higher priority is selected. The priority is computed in the same way than XSLT patterns, but it can also be specified explicitely.

The <xcl:apply-rules> element sends the matched node (that could have been modified) to the next step, and applies the current filter to its content. The next step is specified by the <xcl:forward> element, which can be :

If an <xcl:apply-rules> element is encountered outside a <xcl:forward> element, the node is ignored, but its content is applied on the filter.

If no <xcl:apply-rules> element is found inside a rule, the node and its content are ignored.

If more than one <xcl:apply-rules> elements are found while running a rule, the first is applied, the others are doing nothing.

Within a rule and a <xcl:forward> element, any active tags or litteral are allowed. XML litterals within the <xcl:forward> element are changing the structure of the output document.

Use cases

Forwarding a node as-is

    <xcl:rule pattern="foo">
        <xcl:forward>
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>

Removing a node and its content

    <xcl:rule pattern="foo"/>

Removing a node and apply the filter on its content

    <xcl:rule pattern="foo">
        <xcl:apply-rules/>
    </xcl:rule>

Removing the content of a node

    <xcl:rule pattern="foo">
        <xcl:forward>
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>
    <xcl:rule pattern="foo/node()"/>

As the name of the element to forward is known :

    <xcl:rule pattern="foo">
        <xcl:forward>
            <foo/>
        </xcl:forward>
    </xcl:rule>

But it is slightly different because the incoming element might have attributes whereas the element forwarded has none.

Inserting a node before/after

    <xcl:rule pattern="foo">
        <xcl:forward>
            <before>
                <!--some content-->
            </before>
            <xcl:apply-rules/>
            <after>
                <!--some content-->
            </after>
        </xcl:forward>
    </xcl:rule>

A mix of insert and remove

    <xcl:rule pattern="foo">
        <xcl:forward>
            <before>
                <!--some content-->
            </before>
        </xcl:forward>
        <xcl:apply-rules/>
        <xcl:forward>
            <after>
                <!--some content-->
            </after>
        </xcl:forward>
    </xcl:rule>

Wrapping in a host element

    <xcl:rule pattern="foo">
        <xcl:forward>
            <container>
                <xcl:apply-rules/>
            </container>
        </xcl:forward>
    </xcl:rule>

Inserting an XML fragment from another file

    <xcl:rule pattern="foo">
        <xcl:forward>
            <!--we assume that the file name is inside an attribute :
                <foo file="[some-file-name]">
            -->
            <xcl:parse name="other" output-type="SAX" source="file:///path/to/{ @file }.xml"/>
            { $other }
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>

Renaming the matched element

    <xcl:rule pattern="foo">
        <xcl:rename operand="bar" referent="{ . }"/>
        <xcl:forward>
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>

Operations on attributes

    <xcl:rule pattern="foo">
        <!--add 2 attributes-->
        <xcl:attribute name="new1" referent="{ . }" value="foo"/>
        <xcl:append referent="{ . }">
            <xcl:attribute name="new2" value="foo"/>
        </xcl:append>
        <!--remove an attribute-->
        <xcl:remove parent="{ . }" referent="{ @attrToRemove }"/>
        <!--rename an attribute-->
        <xcl:rename operand="newName" referent="{ @attrToRename }"/>
        <!--change the value of an attribute-->
        <xcl:attribute name="attrToChange" referent="{ . }" value="newValue"/>
        <xcl:forward>
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>

Removing all attributes

    <xcl:rule pattern="removeAllAttr">
        <xcl:remove parent="{ . }" referent="{ @* }"/>
        <xcl:forward>
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>
                

4.3 Channels

Channels allow routing an XML output to an XML input. By connecting filters, a main transparent channel from one to one is used, but additive channels can be defined in order to dispatch the same input to several outputs.

A channel can be global or local.

Global channels

Each channel should be connected to a consumer or to a pipeline connected to a consumer before connecting the main channel to a consumer or to a pipeline connected to a consumer. A disconnected channel would cache its entry which is not desirable in a streaming strategy, but acceptable for tree-based processes.

Channels can be specified as an output of a filter thanks to the @channel attribute of the <xcl:forward> element :

    <xcl:rule pattern="foo">
        <xcl:forward channel="c1 c2 c3">
            <xcl:apply-rules/>
        </xcl:forward>
    </xcl:rule>

...which denotes that the XML datas have to be forwarded to the channels named "c1", "c2", and "c3" which are qualified names.

To connect channels to other filters or consumers, the xcl:channel() function must be used.

A filter that separates elements

This example shows how to separate elements that are in a given namespace in a separate XML stream which is serialized to a file.

    <xcl:parse name="input" output-type="SAX" source="file:///path/to/file.xml"/>
    <xcl:filter name="step" source="{ $input }">
        <xcl:rule pattern="acme:*"
        xmlns:acme="urn:acme-business-model">
            <xcl:forward channel="acme">
                <xcl:apply-rules/>
            </xcl:forward>
        </xcl:rule>
    </xcl:filter>
    <xcl:transform output="file:///path/to/acme-result.xml" source="{ xcl:channel('acme') }"/>
    <xcl:transform output="file:///path/to/other-result.xml" source="{ $step }"/>

Of course, the channel consumed by the <xcl:transform> element could also be the source of a next filter.

Notice that the second channel is connected to its consumer before the main channel. In an event-based process, this is the main channel that drives the pipeline : the pipeline is inactive until the last step is connected to a consumer.

Local channels

Channels can be also be local to a rule.

A filter that split an XML document to several XML documents

This example shows how to create a separate document when an element matches a given pattern.

    <xcl:parse name="input" output-type="SAX" source="file:///path/to/file.xml"/>
    <xcl:filter name="step" source="{ $input }">
        <xcl:rule pattern="/orders/purchase-order">
            <xcl:document name="po" type="SAX">
                <xcl:forward channel="po">
                    <xcl:apply-rules/>
                </xcl:forward>
            </xcl:document>
            <xcl:transform output="file:///path/to/purchase-order-{ @id }.xml" source="{ $po }"/>
        </xcl:rule>
    </xcl:filter>
    <xcl:transform output="file:///path/to/other-result.xml" source="{ $step }"/>

Each time a "purchase order" is matched, a new XML file is created (assuming that the element contains the @id used for naming the output file).

Merging channels

Merging channels is the same as merging XML :

    <!-- ... -->
    <xcl:document type="SAX">
        <root>
            { xcl:channel( 'c1' ) }
            { xcl:channel( 'c2' ) }
            { xcl:channel( 'c3' ) }
        </root>
    </xcl:document>

Predefined channels

2 predefined channels can be used :

4.4 Filter definitions

Filters that intend to be reused can be defined outside the active sheets that are using them. For this purpose, the same element (<xcl:filter>) can be used as the root of the XML filter, but as it stands for a definition, it is not connected to a source : it is defined without the @source and @name attributes.

<?xml version="1.0" encoding="iso-8859-1"?>
<!--A standalone filter definition--> <xcl:filter xmlns:xcl="http://ns.inria.org/active-tags/xcl"> <!--some rules to apply here--> </xcl:filter>

Within the active sheet that will refer to that reusable filter, the <xcl:filter> element must be used with the @filter attribute :

    <xcl:parse name="input" output-type="event" source="file:///path/to/file.xml"/>
    <xcl:filter filter="file:///path/to/myFilter.xcl" name="step" source="{ $input }"/>
    <xcl:transform output="file:///path/to/result.xml" source="{ $step }"/>

It is also possible to parse a filter and to connect it later :

    <!--init some resources-->
    <xcl:parse-filter name="myFilter" source="file:///path/to/myFilter.xcl"/>
    <!--.../...-->

    <xcl:parse name="input" output-type="event" source="file:///path/to/file.xml"/>
    <xcl:filter filter="{ $myFilter }" name="step" source="{ $input }"/>
    <xcl:transform output="file:///path/to/result.xml" source="{ $step }"/>

The same compiled filter can be referred several times safely even in a multi-threaded environment.

4.5 Built-in filters

The rule-based filters seen previously are all dealing with XML sources. For convenience, other kind of filters (not necessary rule-based) can be considered. For example, an implementation can define built-in filters for reading raw text inputs or binary inputs.

When referring to such filters, additional parameters may also be used.

XCL defines the following built-in filters but a given implementation can supply additional filters. The former is an XInclude filter that reads an XML source, the 2 latters are filters that read raw texts.

XInclude filter

This predefined filter performs an XInclude inclusion as specified in the XInclude recommendation.

    <xcl:parse-filter filter="http://ns.inria.org/active-tags/xcl/filters#XInclude" name="xinclude"/>
    <xcl:parse name="xml" source="file:///path/to/file.xml"/>
    <xcl:filter filter="{ $xinclude }" name="included" source="{ $xml }"/>
    <xcl:transform output="file:///path/to/result.xml" source="{ $included }"/>

Filtering plain-text streams

The URI http://ns.inria.org/active-tags/xcl/filters#LineReader is reserved for a filter that can read a plain text stream and stands for an XML producer. When this filter is connected to a consumer (directly or indirectly), it fires events for the begin of the document, for each line read in the input, and for the end of the document.

    <xcl:parse-filter filter="http://ns.inria.org/active-tags/xcl/filters#LineReader"
name="lineReader"/> <xcl:filter filter="{ $lineReader }" name="text" source="file:///path/to/file.txt"/> <xcl:filter name="step" source="{ $text }"> <xcl:rule pattern="/"> <xcl:forward> <poem><xcl:apply-rules/></poem> </xcl:forward> </xcl:rule> <xcl:rule pattern="text()"> <xcl:forward> <line><xcl:apply-rules/></line> </xcl:forward> </xcl:rule> </xcl:filter> <xcl:transform output="file:///path/to/result.xml" source="{ $step }"/>

If the content of the file file:///path/to/file.txt is :

From fairest creatures we desire increase,
That thereby beauty's rose might never die,
But as the riper should by time decease,
His tender heir might bear his memory:
But thou contracted to thine own bright eyes,
Feed'st thy light's flame with self-substantial fuel,
Making a famine where abundance lies,
Thy self thy foe, to thy sweet self too cruel:
Thou that art now the world's fresh ornament,
And only herald to the gaudy spring,
Within thine own bud buriest thy content,
And tender churl mak'st waste in niggarding:
Pity the world, or else this glutton be,
To eat the world's due, by the grave and thee.

Then the output XML file will be (a smart indent has been added, it is not in the real output) :

<?xml version="1.0" encoding="iso-8859-1"?>
<poem> <line>From fairest creatures we desire increase,</line> <line>That thereby beauty's rose might never die,</line> <line>But as the riper should by time decease,</line> <line>His tender heir might bear his memory:</line> <line>But thou contracted to thine own bright eyes,</line> <line>Feed'st thy light's flame with self-substantial fuel,</line> <line>Making a famine where abundance lies,</line> <line>Thy self thy foe, to thy sweet self too cruel:</line> <line>Thou that art now the world's fresh ornament,</line> <line>And only herald to the gaudy spring,</line> <line>Within thine own bud buriest thy content,</line> <line>And tender churl mak'st waste in niggarding:</line> <line>Pity the world, or else this glutton be,</line> <line>To eat the world's due, by the grave and thee.</line> </poem>

Filtering plain-text streams upon a regular expression

The URI http://ns.inria.org/active-tags/xcl/filters#Tokenizer is reserved for a filter that can tokenize a plain text stream regarding a regular expression, and stands for an XML producer. When this filter is connected to a consumer (directly or indirectly), it fires events for the begin of the document, for each string around the tokens matched by the regular expression (tokens are stripped), and for the end of the document.

It accept the following parameters :

NameValueDefault
patternThe pattern used for the tokenization\s*
flagsThe options for the interpretation of the regular expression
bufferThe size of the buffer (char size)2048

The buffer size is used to store chunks of stream on which the regular expression is applied ; if nothing matches, the content of the buffer is used to fire a single character event. If the buffer is not big enough for the regular expression to be applied entirely, unexpected results might occur.

    <xcl:parse-filter filter="http://ns.inria.org/active-tags/xcl/filters#Tokenizer" name="tokenizer">
        <xcl:param name="pattern" value=",\s*"/>
        <xcl:param name="buffer" value="1024"/>
    </xcl:parse-filter>

5 Fallback processing and definition

When an action fails to run, it may invoke a fallback procedure with a failure cause and error datas.

The <xcl:fallback> element may be used as a local definition of a fallback process that will be invoked if its host action fails to run. Several elements may be defined for a single host action ; each must have an @id attribute different that identifies a fallback process, except one that is the default fallback action. When the host action fails to run, the fallback action that has the same identifier than the failure cause will be invoked ; if no fallback action matches the failure cause, the lookup of the fallback action is performed on the ancestors of the action that fails ; if still not found, the lookup sequence is tried again to find a default fallback action.

Recovering a fatal error while XML parsing

In this example, after running the <xcl:parse> element, the $result property will contain a parsed XML document that contains :

  • either the parsed source file,
  • or a report error.
    <xcl:parse name="result" source="file:///path/to/file.xml">
        <xcl:fallback id="xml:fatal-error">
            <xcl:document name="result">
                <error column="{ $xml:x-error/@column-number }" level="{ name( $xml:x-error ) }"
line="{ $xml:x-error/@line-number }" public-id="{ $xml:x-error/@public-id }"
system-id="{ $xml:x-error/@system-id }"> { string( $xml:x-error ) } </error> </xcl:document> </xcl:fallback> </xcl:parse>

The fallback process will be invoked only on fatal error as specified in the XML recommendation ; if it occurs, it will be invoked with the $xml:x-error property which contains the detailed informations about the error.

Reusable fallback definitions

There is 2 ways to reuse a fallback definition :

Using fallback definitions at a higher hierarchy level

As both parsing actions below may cause the same error, a higher element in the tree hierarchy defines a common fallback process that will be used if a fatal error occurs when parsing :

    <xcl:block>
        <xcl:parse name="result1" source="file:///path/to/file1.xml"/>
        <xcl:parse name="result2" source="file:///path/to/file2.xml"/>
        <xcl:fallback id="xml:fatal-error">
            <xcl:document name="result">
                <error column="{ $xml:x-error/@column-number }" level="{ name( $xml:x-error ) }"
line="{ $xml:x-error/@line-number }" public-id="{ $xml:x-error/@public-id }"
system-id="{ $xml:x-error/@system-id }"> { string( $xml:x-error ) } </error> </xcl:document> </xcl:fallback> </xcl:block>

Reusing another fallback definition

As different kind of errors may occur while parsing, it is often convenient to define a single fallback action and tell others to use it :

    <xcl:parse name="result" source="file:///path/to/file.xml">
        <xcl:fallback id="xml:fatal-error">
            <xcl:document name="errors" xcl:if="{ not( $errors) }">
                <errors/>
            </xcl:document>
            <xcl:append referent="{ $errors/errors }">
                <error column="{ $xml:x-error/@column-number }" level="{ name( $xml:x-error ) }"
line="{ $xml:x-error/@line-number }" public-id="{ $xml:x-error/@public-id }"
system-id="{ $xml:x-error/@system-id }"> { string( $xml:x-error ) } </error> </xcl:append> </xcl:fallback> <xcl:fallback id="xml:error" use="xml:fatal-error"/> <xcl:fallback id="xml:warning" use="xml:fatal-error"/> </xcl:parse>

Both of these techniques may be mixed.

Recovering errors

The x-error type represent all kind of errors.

An error is recovered when after running the fallback process the interrupted process goes on. In fact, each error object is defined with a flag that indicates if it can recover the process or not. For example, xml:fatal-error is not a recoverable error, whereas xml:warning is. However, during the fallback process -if any- the recover status may be changed.

At the end of a fallback process, if the error is recoverable, the process will go on at the point that cause the error ; if the error is not recoverable the process will go on after the host action that defines the fallback process that was selected.

Custom errors

The <xcl:error> element allows to cause a user defined error.

An error object may be composed of any arbitrary field, exposed as attributes as well as content.

    <xcl:block>
        <!-- let's prepare a boat trip -->
        <xcl:if test="{ $acme:boat/@has-sunk }">
            <xcl:then>
                <xcl:error id="acme:sunk-boat" recover="yes">
                    { $boat }
                    <detail>This boat has sunk !!!</detail>
                </xcl:error>
            </xcl:then>
        </xcl:if>
        <!--
            do the boat trip...
        -->
        <xcl:fallback id="acme:sunk-boat">
            <!-- raising the boat -->
        </xcl:fallback>
    </xcl:block>

Errors in fallback processes

As a new error may occur while recovering an error, the lookup process must be blocked by the current fallback action.

However, it is still possible to define a fallback action within another fallback action. If necessary, the inner fallback action may refer to its host fallback action but this must be done with care because the whole process may loop.


6 XCL module reference

XCL : XML Control Language
XCL namespace URI : http://ns.inria.org/active-tags/xcl
Usual prefix : xcl
Elements Foreign attributes Predefined properties Extended functions Data types
<xcl:active-sheet>
<xcl:logic>
<xcl:parse>
<xcl:parse-html>
<xcl:parse-stylesheet>
<xcl:transform>
<xcl:parse-type>
<xcl:document>
<xcl:element>
<xcl:attribute>
<xcl:namespace-declaration>
<xcl:comment>
<xcl:processing-instruction>
<xcl:text>
<xcl:operations>
<xcl:commit>
<xcl:rollback>
<xcl:append>
<xcl:clear>
<xcl:clear-all>
<xcl:insert-after>
<xcl:insert-before>
<xcl:remove>
<xcl:rename>
<xcl:replace>
<xcl:update>
<xcl:call>
<xcl:if>
<xcl:then>
<xcl:else>
<xcl:choose>
<xcl:when>
<xcl:otherwise>
<xcl:for-each>
<xcl:loop>
<xcl:break>
<xcl:continue>
<xcl:exit>
<xcl:echo>
<xcl:fallback>
<xcl:error>
<xcl:nop>
<xcl:set>
<xcl:item>
<xcl:param>
<xcl:parse-filter>
<xcl:filter>
<xcl:rule>
<xcl:forward>
<xcl:apply-rules>
@xcl:version
@xcl:if
@xcl:timeout
@xcl:traverse
$xcl:this
$xcl:interrupt
$xcl:interrupted
xcl:sort()
xcl:reverse()
xcl:group()
xcl:distinct()
xcl:canonical-path()
#xcl:filter

Must be an adt:expression that computes an object of the type expected.
Must be a hard-coded value (litteral)
Can be either a hard-coded value or an adt:expression
This material may be missing
Denotes a value to use by default
Allows a read operation.
Allows a write operation.
Allows a rename operation.
Allows an update operation.
Allows a delete operation.

6.1 Elements

<xcl:active-sheet>

Convenient root element for an active sheet that is not an Active Document.

runtime phase

The processor instance that unmarshals this active sheet may invoke a given logic procedure thanks to the EXP invokation mechanism (<exp:invoke>).

Otherwise, the default logic procedure is launched. If none has been defined, the main logic procedure is launched.

[TODO: content definition]

<xcl:logic>

Defines a logic procedure. A logic procedure marks the bound of the scope of local properties.

Must be a child of the <xcl:active-sheet> element.

runtime phase

Run the subactions.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codednameoptional#xs:QName

The name of the logic procedure. If missing, this logic procedure is the default logic procedure. Only one default logic procedure may be defined per active sheet.

[TODO: content definition]

<xcl:parse>

Parses an XML document. While parsing, the catalogs known by the processor instance may be used for entity resolution and validation.

The document to parse must be specified either with the @source attribute or with the @text-source attribute.

The @public-id and @system-id attributes may be used to set (as an expression) a specific external identifier for this document ; this external identifier will not be used to retrieve the input source, but will be used as the base URI for external entity resolution (DTD, entities, etc) ; if just a public identifier is supplied and the source has no system identifier (in the cases when the source to parse is a text or an #io:input), the public identifier will be lookup within the catalogs, and the resolved URI will be used as the base URI.

runtime phase

error handling phase

If an error is encountered while parsing and <xcl:fallback> elements are children of this element, they will be invoked according to their identifier, and the parsing may goes on :

IDCondition of invokation
xml:warning A warning occurs, in the conditions specified in the XML recommendation
xml:error A recoverable error occurs, in the conditions specified in the XML recommendation
xml:fatal-error A non-recoverable error occurs, in the conditions specified in the XML recommendation

Each of the fallback actions above will be invoked with the same data set as those used when the parsing starts. A property of the type #xml:x-error is previously added.

Additionally, a default <xcl:fallback> element may be supplied.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothsourceoptional#io:x-file The XML file to parse.
#io:input The XML input stream to parse.
#xs:anyURI The URI of the XML document to parse.
bothtext-sourceoptional#xs:string The string to parse.
bothstyleoptional Specifies the type of XML document to produce.
#xs:stringtreedefault valueA tree-based document (DOM).
eventAn event handler (SAX). In this case, the parsing is deferred until the handler is consumed.
bothmodeoptional Specifies the mode of parsing (if XML fragments have to be parsed).
#xs:stringstrictdefault valueOnly well-formed XML documents will be parsed sucessfully.
laxXML fragments and well-formed XML documents will be parsed sucessfully.
hard-codedvalidateoptional Specifies if the parser will validate documents as they are parsed.
#xs:stringyes Validates the document according to the relevant resources :
  • a reference to the DTD.
  • a reference to the W3C XML Schema.
  • the namespace URI of the elements and attributes encountered ; in this case, the schemas will be looked up in the catalog.
nodefault valueNo validation.
hard-codednamespace-awareoptional Specifies if the parser will provide support for XML namespaces.
#xs:stringyesdefault valueThe document is namespace aware.
noThe document is not namespace aware.
hard-codedcoalesceoptional Specifies that the parser will convert CDATA nodes to Text nodes and append it to the adjacent (if any) text node.
#xs:stringyesCoalesce text.
nodefault valuePreserve CDATA sections.
hard-codedexpand-entity-refoptional Specifies that the parser will expand entity reference nodes.
#xs:stringyesdefault valueExpands entity references.
noDon't expand entity references.
hard-codedignore-whitespaceoptional Specifies if the parser must eliminate whitespace in element content (sometimes known loosely as 'ignorable whitespace') when parsing.
#xs:stringyesIgnores the whitespaces if the parser is validating.
nodefault valuePreserve the whitespaces.
hard-codedpreferoptional Specifies if a catalog must be used or not ; specifies when a catalog have to be used which lookup strategy regarding public/system identifiers to apply, according to OASIS XML Catalog specification.
missing attributedefault value No catalog will be used.
#xs:string""The catalog of this processor will be used, without specifying what is preferred.
publicThe catalog of this processor will be used, preferring public IDs.
systemThe catalog of this processor will be used, preferring system IDs.
[TODO: content definition]

<xcl:parse-html>

Parses an HTML document to an XML document.

The document to parse must be specified either with the @source attribute or with the @text-source attribute.

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothsourceoptional#io:x-file The HTML file to parse.
#io:input The HTML input stream to parse.
#xs:anyURI The URI of the HTML document to parse.
bothtext-sourceoptional#xs:string The string to parse.
[TODO: content definition]

<xcl:parse-stylesheet>

Parses a XSLT stylesheet. While parsing, the catalogs known by the processor instance will be used for URI resolution.

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothsource#xml:document The stylesheet to parse.
#io:x-file The stylesheet to parse.
#io:input The input stream stylesheet to parse.
#xs:anyURI The URI of the stylesheet to parse.
bothsystem-idoptional#xs:string The system ID to set to the stylesheet.
[TODO: content definition]

<xcl:transform>

Transform an XML source with an XSLT stylesheet. While transforming, the catalogs known by the processor instance may be used for URI resolution.

The output of the XSLT transformation may be handled by a property if :

A stylesheet may accept parameters ; those that are bound to the XSLT namespace URI override the output properties specified in the stylesheet :

<xcl:transform output="/path/to/doc.html" source="/path/to/doc.xml"
stylesheet="/path/to/stylesheet.xsl"> <xcl:param name="date" value="{ $date }"/> <xcl:param name="page" value="1"/> <!--override the encoding specified in the stylesheet, or set it if unspecified in the stylesheet--> <xcl:param name="xsl:encoding" value="iso-8859-1"/> </xcl:transform>

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothsource#xml:node The node to transform.
#io:x-file The XML file to transform.
#io:input The XML input stream to transform.
#xs:anyURI The URI of the XML document to transform.
bothstylesheetoptional

If the same stylesheet have to be used several times, use <xcl:parse-stylesheet> to produce a #xsl:stylesheet object.

#xsl:stylesheet The parsed stylesheet.
#io:x-file The stylesheet file to parse.
#io:input The input stream stylesheet to parse.
#xs:anyURI The URI of the stylesheet to parse.
hard-codedoutput-typeoptional Specifies the type of the output.
#xs:stringtreeProduce a tree-based document (DOM).
eventProduce an event handler (SAX). In this case, the transformation is deferred until the handler is consumed.
streamdefault value Produce a character stream. The @output attribute may be specified.
bothoutputoptional Specifies a file for saving the output. Can be used only if output-type="stream".
#io:x-file The file to save to.
#io:output The output stream to write to.
#xs:anyURI The URI to save to.
hard-codedstylesheet-selectoroptional Specifies the selector to use for catalog lookup of the stylesheet. If the @stylesheet attribute doesn't refer to a pre-compiled stylesheet, a catalog lookup will be perform only if this attribute is present. See Active Catalog specification.
#xs:string""The catalog is invoked without a selector.
#xs:QNamexsl:stylesheet The selector with which the catalog is invoked. The catalog will invoke a post-process that should deliver a parsed stylesheet.
The selector with which the catalog is invoked.
hard-codeddocument-selectoroptional Specifies the selector to use for catalog lookup when the XSLT processor encounters <xsl:import>, <xsl:include>, or document()() ; a post-process should deliver a resolved URI or an XML document. A catalog lookup will be perform only if this attribute is present. See Active Catalog specification.
#xs:string""The catalog is invoked without selector.
#xs:QName The selector with which the catalog is invoked.
[TODO: content definition]

<xcl:parse-type>

Parse a value to a typed data. If needed, the catalogs known by the processor instance will be used to retrieve the schema that defines the type.

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
hard-codedtype#xs:QName The type name.
runtimevalue#xs:string The text to parse.
#other The text to parse, taken from the string value of the object given.
[TODO: content definition]

<xcl:document>

Create an XML document.

runtime phase

In both cases, the #xml:document created is either set to a property with the name specified by the @name attribute, or set to the current object.

Building the document :

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
hard-codedtypeoptional Specifies the type of the XML document.
#xs:stringtreedefault valueProduce a tree-based document (DOM).
eventProduce an event handler (SAX).
[TODO: content definition]

<xcl:element>

Create an #xml:element. If this action is encountered while consuming an event handler, the element produced will be an event, otherwise the element produced will be a tree-node.

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothname#xs:QName The name of the element.
runtimecontentoptional#xml:node The content of the element.
#adt:list of #xml:node The content of the element. Each item is appended separately.
#adt:map of #xml:node (by definition, all the nodes in the map have a name) The content of the element. Each item is appended separately.
[TODO: content definition : dynamic content : <xml:node> - <adt:list> of <xml:node>s - <adt:map> of <xml:node>s]

<xcl:attribute>

Create an XML attribute, or set an attribute on behalf of a referent.

runtime phase

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
runtimereferentoptional#any object A reference to an object on which to set the attribute. If missing, the attribute feeds the current context.
bothnameoptional#xs:QName

The name of the attribute to set or to create.

bothvalueoptional#any object The value of the attribute. If missing, the value is given by subactions.
hard-codednormalizeoptional Indicates whether the attribute text value has to be normalized or not.
#xs:booleanfalsedefault valueThe attribute value is left as is.
trueThe attribute value is convert to text and normalized.
[TODO: content definition]

<xcl:namespace-declaration>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:comment>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:processing-instruction>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:text>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:operations>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:commit>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:rollback>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:append>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:clear>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:clear-all>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:insert-after>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:insert-before>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:remove>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:rename>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:replace>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:update>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:call>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:if>

An alternative action.

runtime phase

Perform a test, and run one of the subactions <xcl:then> or <xcl:else> according to the result of the test.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
runtimetest The test to perform.
#xs:booleantrueRun <xcl:then>.
falseRun <xcl:else>.

<xcl:then>

An alternative branch to perform if the test evaluated by its parent <xcl:if> element is true.

[TODO: content definition]

<xcl:else>

An alternative branch to perform if the test evaluated by its parent <xcl:if> element is false.

[TODO: content definition]

<xcl:choose>

Group several alternative actions.

runtime phase

Perform the tests of its <xcl:when> subactions. The first that is true is performed. If none, the <xcl:otherwise> element is performed if any.


<xcl:when>

An alternative branch to perform if the test evaluated by its @test attribute is true.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
runtimetest The test to perform.
#xs:booleantruePerform the subactions.
falseSkip the subactions.
[TODO: content definition]

<xcl:otherwise>

An alternative branch to perform if no previous <xcl:when> action has been performed.

[TODO: content definition]

<xcl:for-each>

Iterates on items.

runtime phase

If the @name attribute is specified, a property will be created while iterating ; its value will be those of each item selected. At the end, the property created will be discarded.

Otherwise, the current object will be set to each item selected.

If the @select attribute returns an object reference that is not a collection, a single iteration is performed with the object returned as the item to iterate.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothname#xs:QName The name of the item on each iteration.
runtimeselect#adt:expression An expression that selects the items for the iteration.
[TODO: content definition]

<xcl:loop>

Loops as long as a condition is true.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
runtimetest The test to perform.
#xs:booleantruePerform the subactions.
falseExit the loop.
[TODO: content definition]

<xcl:break>

Break an iteration.


<xcl:continue>

Continue to the next iteration.


<xcl:exit>

Exit a logic procedure.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codedlevel The number of logic procedure to exit. If missing, the current logic procedure is leaved.
#xs:int0Leave all logic procedure.
otherLeave the number of logic procedure specified.

<xcl:echo>

runtime phase

Print a value to the standard output.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothvalueoptional#xs:QName The value to print.

No content is allowed.


<xcl:fallback>

A fallback action may be defined on behalf of any element that might fail to run.

unmarshal phase

Register this fallback action to its host action.

runtime phase

A fallback action is invoked only when selected when an error occurs on its host action.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codedidoptional#xs:QName The identifier of this action. This action will be selected if the error has the same identifier. The default fallback action has no identifier.
hard-codeduseoptional#xs:QName When several fallback actions have to perform the same actions sequence, one will describe it, the others will refer to it.

When specified, indicates which other fallback action to run. The target fallback action must be in the scope of the host action : one of the siblings or one of the fallback action of its ancestors.


<xcl:error>

Cause an error.

runtime phase

Create an error object and interrupt the current execution. The fallback action defined in the nearest ancestor of its parent action that has the same identifier of this error is selected if any ; otherwise the default fallback action is selected if any.

The error object is created by :

  1. openning a context,
  2. runnning its content,
  3. setting the content of the error with all items found in the context.
Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codedid#xs:QName The identifier of this error. This is also the name of the property that hold the error object.
hard-codedrecoveroptional Indicates the default behaviour after invoking the fallback action. This is a default behaviour in the sense that it can be updated on the pending error object arbitrarily while running the fallback action.
#xs:booleantrueContinue after the interruption.
falseGo on after the parent action of the fallback action that was selected.
[TODO: content definition]

<xcl:nop>

runtime phase

[TODO: attributes] [TODO: content definition]


<xcl:set>

Assign a value to a property.

runtime phase

A property is added to the dataset.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothvalueoptional#any object The value to set to the property. If missing, the value is given thanks to subactions.
[TODO: content definition]

<xcl:item>

Adds an item to the current context.

runtime phase

This element behaves like the <xcl:set> element, except that it doesn't create a property but feeds the context. If the @value attribute is missing, refer to the <xcl:set> element.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of the item.

bothvalueoptional#any object The value to set to the item. If missing, the value is given thanks to subactions.
[TODO: content definition]

<xcl:param>

Define a parameter.

runtime phase

Feeds the current parameter context with an item that may have a name.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of the parameter.

bothvalueoptional#any

The value of the parameter.

[TODO: content definition]

<xcl:parse-filter>

Parses a filter definition (rule-based or built-in).

runtime phase

Put a #xcl:filter in the data set or set it to the current object, according to the presence of the @name attribute.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of a property.

hard-codedscopeoptional The scope of the property to create.
#xs:stringlocaldefault valueLocal.
globalGlobal.
sharedShared.
bothsourceoptional#xs:anyURI The URI of the filter to parse.
#io:file The file to parse as a filter.

<xcl:filter>

Define a filter, or connect a filter to a pipeline.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
bothnameoptional#xs:QName

The name of the filter. An external filter doesn't specify a name.

bothsourceoptional#xml:document The input document to filter, when this element is a pipeline connector.
#xs:anyURI The URI of the input file to filter, when this element refers to a standalone filter.
#io:file The input file to filter, when this element refers to a standalone filter.
runtimefilteroptional#xcl:filter

A reference to the filter.

hard-codednormalizeoptional Specifies the default behaviour of a rule-based filter definition regarding adjacent text nodes. It can be overriden by any rule defined within.
#xs:stringyes Adjacent text nodes are merged.
nodefault value Text nodes are kept as-is.
[TODO: content definition]

<xcl:rule>

Define a rule within a rule-based <xcl:filter>.

A rule is applied when its XPath pattern matches a candidate node.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codedpattern#adt:pattern

The XPath pattern for this rule.

hard-codedpriorityoptional Specifies the default behaviour of a rule-based filter definition regarding adjacent text nodes. It can be overriden by any rule defined within.
#xs:double The specific priority for this rule.
missing attributedefault value The priority is intrinsic to the pattern. It is computed in the same way than with XSLT patterns.
hard-codednormalizeoptional Specifies the behaviour regarding adjacent text nodes.
#xs:stringyes Adjacent text nodes are merged.
no Text nodes are kept as-is.
missing attributedefault value The behaviour is those specified by the filter.
[TODO: content definition]

<xcl:forward>

Forward some node to the next step of a pipeline.

Attributes runtime | hard-coded | both
NameTypeValue optional | default value
hard-codedchanneloptional Specifies the channels to forward to.
#xs:QName#maindefault value The "main" channel is the channel to which is connected the filter.
#self The "self" channel is a loopback to the filter to which belongs this rule.
Any channel name.
#adt:list of #xs:QName A list of channel names, that can also contains #main or #self, but not both.

<xcl:apply-rules>

Apply the filter on the content of the node that matches the current rule.

If this element is not encountered within a rule, the node that matched and its content will be ignored by the filter.

6.2 Foreign attributes

@xcl:version

The version of the XCL module to use. This attribute should be encountered before any XCL element, but it takes precedence on the element inside which it is hosted.


@xcl:if

This foreign attribute is a quick alternative to <xcl:if> <xcl:then> statements.

This foreign attribute is conditionning the action within which it is hosted.

Instead of :

    <xcl:if test="{ @boat-name = 'titanic' }">
        <xcl:then>
            <acme:sink boat="{.}"/>
        </xcl:then>
    </xcl:if>

...it is possible to do the same with :

    <acme:sink boat="{.}" xcl:if="{ @boat-name = 'titanic' }"/>
TypeValue runtime | hard-coded | both
runtime#xs:booleantrueThe host action is performed.
falseThe host action is ignored.

@xcl:timeout

This foreign attribute sets a timeout on its host element.

When the timeout is reached, the $xcl:interrupt property signals the inner actions to cancel their process.

After interrution, the $xcl:interrupted status property is set to indicate that the host active tag was cancelled (this property is unset before running the operations).

TypeValue runtime | hard-coded | both
hard-coded#xs:int The delay in milliseconds after which the actions must be cancelled.

@xcl:traverse

This foreign attribute allow to traverse the content of an element without performing it.

TypeValue runtime | hard-coded | both
runtime#xs:booleantrueThe host action is ignored : only its content is performed.
falseThe host action is performed as usual.
[TODO[

@xcl:traverse, @xcl:ignore and @xcl:run-once should be exposed with a single attribute : @xcl:run="traverse|ignore|once"

]]

6.3 Predefined properties

$xcl:this

  • Property type: #xml:document
  • $xcl:this is a reference to the active sheet.


    $xcl:interrupt

    Signal that the current action must be interrupted.

    The value is implementation dependant.


    $xcl:interrupted

    Set when an action was interrupted.

    The value is implementation dependant.

    6.4 Extended XPath functions

    xcl:sort()

  • Return: #adt:list of #items
  • Sort a list of items regarding sorting criteria.

    Arguments
    1#adt:list of #items The items to sort.
    2XPath argument A sorting criterion. A relative path is applied on each item to sort.

    Several sorting criteria may be specified :

    xcl:sort( $foo/foo, @name, @type, bar/text() )

    In the context of a sort criterion, the xcl:reverse() function will sort in the reverse order :

    xcl:sort( $foo/foo, @name, xcl:reverse( @type ), bar/text() )

    If all criteria must be reversed, the xcl:reverse() function may be factorized :

    xcl:sort( $foo/foo, xcl:reverse( @name ), xcl:reverse( @type ), xcl:reverse( bar/text() ) )

    ...is equivalent to :

    xcl:reverse( xcl:sort( $foo/foo, @name, @type, bar/text() ) )

    xcl:reverse()

    Reverse the order of a list, or reverse the order of a sorting criterion.

    Arguments
    1#adt:list of #items The list to reverse. When used out of the context of a sorting criterion
    Arguments
    1XPath argument The sorting criterion to reverse. Applied on each item to sort. When used at the place of a sorting criterion.

    Out of the context of a sorting criterion :

    xcl:reverse( $foo/foo )

    Inside the context of a sorting criterion (xcl:sort()) :

    xcl:sort( $foo/foo, @name, xcl:reverse( @type ), bar/text() )

    Both expressions below are equivalent :

    xcl:sort( $foo/foo, @name, @type, bar/text() )
    xcl:reverse( xcl:sort( $foo/foo, xcl:reverse( @name ), xcl:reverse( @type ), xcl:reverse( bar/text() ) ) )

    xcl:group()

  • Return: #adt:list of #adt:list of #items
  • Group a list of items regarding grouping criteria.

    Arguments
    1
    #adt:list of #items The items to sort.
    #other An object that have children to sort.
    2...nXPath argument A sorting criterion. A relative path is applied on each item to group.

    Several grouping criteria may be specified :

    xcl:group( $foo/foo, @name, @type, bar/text() )

    This function intends to be used for browsing the result list sequentially (the outer list), and each of its sublist sequentially (the inner lists). As the outer list just contains other lists, this function also set the current object while the outer list is browed ; each time a new group is encountered according to the criteria, the first item of the group is set as the current object, so that next actions can handle the current values of the grouping criteria before starting browsing the current inner list.

    Once an inner list is supplied as the current item of the outer list, if the outer list goes on browsing without waiting the end of the current inner list, a new inner list is created starting at the first item available of the previous inner list.

    xcl:group() doesn't sort by itself the list to group.


    xcl:distinct()

    [TODO[The same function as xcl:group(), but the outer list is stripped.]]

    xcl:canonical-path()

  • Return: #adt:QNameSet
  • Compute the canonical path of a node, that is to say a string made of #xs:QNames with the namespace URI bindings.

    Arguments
    1#xml:node The node.

    6.5 Data types

    #xcl:filter type

    An XCL filter.


    Appendix

    A Glossary

    B Related Active Tags specifications

    This list is not exhaustive; it is a list of common modules usable by an engine that implements the Active Tags specifications that implementors may use. Additional modules are welcome.

    C Lists

    C.1 Examples list

    D Active Schema for XCL

    [schema.asl]

    <asl:active-schema asl:version="1.0" target="xcl" schema-version="1.0" xml:lang="en"
        xmlns:xcl="http://ns.inria.org/active-tags/xcl"
        xmlns:asl="http://ns.inria.org/active-schema"
        xmlns:adt="http://ns.inria.org/active-datatypes"
        xmlns:xs="http://www.w3.org/2001/XMLSchema-datatypes"
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:at="http://ns.inria.org/active-tags/reference">
    
        <asl:element name="xcl:active-sheet" root="always">
        </asl:element>
    
        <!-- TODO -->
    
    </asl:active-schema>