XSLT transformations

A transformation expressed in XSLT describes rules for transforming a source tree into a result tree. In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.
For complete information about XSLT standard see http://www.w3.org/TR/xslt .

Not everything stated in the standard is implemented in the system, and some things work differently. If you want to apply transformations you need two things :

  1. A source document that can be any well-formed XML document.
  2. A transformation document that contains the transformation rules.
The rest of this review will be concerned with transformation document.

1. Basic structure of the transformation document (TD).

Any tag name, used below, may be optionally preceded by the XSLT namespace: "xsl" prefix. So tag named "template" may be also written as "xsl:template".

This is a description of the syntax of the TD. For details of how the XSLT processor work see below.

1.1. The root.

The root of every TD must be either "transform" or "stylesheet" tag.

1.2. Children of the root.

A transform (stylesheet) contains a set of "template" rules.

1.3. Templates.

A template is instantiated for a particular source element to create part of the result tree. Template rules identify the nodes to which they apply by using a pattern.

Attributes of the "template" tag

Children of the "template" tag.

Anything can be put as child to a template tag, but some tag names have special meaning.

  1. "apply-template" tag
    This tag tells the XSLT processor to continue applying the rules. Typically, apply-templates is used to process only nodes that are descendants of the current node.

    The "apply-template" tag can have optional "sort" children.

  2. "for-each" tag

    This tag apply its content to every node it selects. Its content is similar in every way to the content of a "template" tag and is similarly used, but it may have "sort" tag children that determine the order of processing of the nodes.
    Attributes :

  3. "sort" tag

    The "sort" tag determines the key for sorting of the lists, resulting from XPath expression. When no such tag occurs, the list are processed in document order. Otherwise, they are first sorted. The first sort child determines the first key, the second sort child - the second key and so on.

    Sorting is specified by adding sort elements as children of an xsl:apply-templates or for-each element.

    The "sort" tags may appear as children of "for-each" and "apply-templates" tags. Elsewhere it is considered as a normal tag without special meaning.

  4. "if" tag

    This tag contains a XPath that is evaluated (or casted) to boolean. If the answer is true, then the processor applies the content of the tag to the current node. Otherwise it does nothing.

  5. "copy-of" tag

    The copy-of element can be used to insert a result tree fragment into the result tree. This element contains a XPath, that is evaluated either to list of nodes, or to boolean, number or string. In the first case each of the selected nodes together with its subtree is attached to the result. In the last cases the XPath is converted to string and is then added to the result tree.(As value-of does)

  6. "copy" tag

    This tags copies the current node and its attributes. The subtree is not copied. No attributes are defined for this tag.

  7. "value-of" tag

    This element is instantiated to create a text node in the result tree.

2. XSLT processor.

The XSLT processor takes as input a source document (SD) and a transformation document (TD) and returns a new document that is called the result document (RD). Its works as follows :

  1. Finds the template that matches the document element of the SD and has mode "" and highest priority.

  2. Applies that template. In the template there may be "apply-template" tags that run the processor recursively. Every node that has no special meaning is attached to the result tree in the right position node (RP). At first this RP is the document node of the RD itself. For more information see the examples below. As one may see, the resulting document may not have only one root. To avoid this, only the first child of the Document node is actually used. This is not valid when you apply the transformation inside the document rather than to the entire document.

  3. Examples.

    The “books” example.

    Lets assume that we have a set of "books", and every "book" tag has 0 or more "author" tags. We want to extract all the authors and put them in a new document. The following XSLT document will do the job.

    Example :
    <books>
    <book>
    <title> Alice in Wonderland </title>
    <author> Louis Carol </author>
    </book>
    <book>
    <title>2001 HPSG-based syntactic TreeBank of Bulgarian (BulTreeBank).</title>
    <author> Simov K </author> <author> Popova G </author>
    <author> Osenova P </author>
    </book>
    <book>
    <title>Creatures of Light and Darkness</title>
    <author> Roger Zelazny </author>
    </book>
    <book>
    <title>The Chronicles of Amber </title>
    <author> Roger Zelazny </author>
    </book>
    </books>

    Note :We will use the "//" for comments. They are not part of the TD.

    <transform>
    <template match="*">
    // the only template that matches every tag
    <authors> // this tag has no special meaning
    <for-each select="child::book/child::author"> // for every author of every book
    <sort/> // sort the authors
    <copy-of select="."/> // copy its "author"s tags
    </for-each> // end cycle
    </authors>
    </template>
    // end template
    </transform> // end the TD

    The result will be:

    <authors>
    <author> Louis Carol </author>
    <author> Osenova P </author>
    <author> Popova G </author>
    <author> Roger Zelazny </author>
    <author> Roger Zelazny </author>
    <author> Simov K </author>
    </authors>

    As one may see, we will have authors that are mentioned more than once in the RD. Lets fix this! The new SD will be the old RD, and the transformation is this :

    <transform>
    <template match="authors">
    // match the root
    <copy> // copy the root
    <apply-templates/> // apply-templates to its children
    </copy>
    </template>
    <template match="author">
    // match every author
    <if test="(. != following-sibling::author[1])">// check if it’s the same as its next sibling
    // note that the authors are sorted.
    <copy-of select="."/>
    </if>
    </template>
    </transform>

    And the final result is:

    <authors>
    <author> Louis Carol </author>
    <author> Osenova P </author>
    <author> Popova G </author>
    <author> Roger Zelazny </author>
    <author> Simov K </author></authors>