chris000r
chris000r

Reputation: 297

XSLT identity transformation

I am new to XSLT and got a technical question about the identity transformation.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

This is a often posted example, but I never found something about the detailed program sequence. I often read that it works recursively. But I am not sure about the detailed process. The template matches the union of all attribute-nodes and all other nodes except the root-node. Then the xsl:copy copies the current contextnode (there is no for-each?!) (which should be the first in the document) and applies the template again with the same choice of nodes. This will be done until all nodes are processed?

I would like to know how the program flow is in that identity-building.

==FOLLOW-UP==

Ok, thanks for your answers. I know the processing model of XSLT roughly. Please have a look onto the following. I define a template, which should result in a set of all nodes (except the root node). Then I want to see whats in that set of nodes. For that purpose, I use a for-each and select the name of the current context node.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="@* | node()">
    <xsl:for-each select="node()">
        <xsl:value-of select="name()" />
    </xsl:for-each>
</xsl:template>

</xsl:transform>

with that input xml:

<Telefonliste>
    <Eintrag>
        <name>Peter</name>
        <nachname>Pan</nachname>
        <Tel>12345</Tel>
    </Eintrag>
    <Eintrag>
        <name>Max</name>
        <nachname>Mustermann</nachname>
        <Tel>98765</Tel>
    </Eintrag>
</Telefonliste>

I would expect, that I get 9 nodes back. (Telefonliste, Eintrag, name, nachname, Tel, Eintrag, name, nachname, Tel) But I get only two nodes back: Eintrag, Eintrag.

Can someone explain that? I thought my matching template matches "all nodes"?

Upvotes: 0

Views: 826

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116959

The identity transform template matches any node (except the / root node). It copies the matched node and applies templates to its children.

The very first node to be matched is the root element. From there, the processing moves down to its children and so on until the entire tree has been processed recursively (assuming there are no overriding templates).


Added:

I would expect, that I get 9 nodes back. (Telefonliste, Eintrag, name, nachname, Tel, Eintrag, name, nachname, Tel) But I get only two nodes back: Eintrag, Eintrag.

Your template is applied exactly once, to the root Telefonliste element. From there, your xsl:for-each instruction processes the two child Eintrag nodes. No further processing takes place, because none was specified (you have no xsL:apply-templates instruction).

I interpreted the match-rule that it matches all nodes in that xml-tree. My papers (from university) underline everywhere, that such queries return a set of nodes, so I thought it collects every node in the tree.

You need to distinguish between a select expression and a match pattern.

  • A select expression selects all nodes for which the expression evaluates as true.

  • A match pattern, on the other hand, selects nothing. A match pattern is used by the XSLT processor to find the best-matching template to apply to the currently processed node.

The usual order is this: an xsl:apply-templates instruction selects a node-set to be processed. For each node in the node-set, the processor selects which template to apply from among the stylesheet's templates (or from the built-in default templates, if no matching template is found). If the template contains an xsl:apply-templates instruction, the process is repeated.

Upvotes: 3

Michael Kay
Michael Kay

Reputation: 163262

The difference between the identity template and your example template using "for-each" is that the identity template uses <xsl:apply-templates/> to process its children. This finds the best matching template rule to process each child, and in each case this is the identity template again, so processing recurses down the tree structure. But in your example template, you process the children of the selected node and output their names, but you make no attempt to apply templates to the children, so there is no recursion.

Upvotes: 3

Related Questions