Is there a way to avoid processing of already processed nodes?
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>node1.1</node1>
<node2>node2.1</node2>
<node2>node2.2</node2>
<node1>node1.2</node1>
</root>
XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="root">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="node1">
[Node1]:<xsl:value-of select="."></xsl:value-of>
<xsl:apply-templates select="following-sibling::node2"/>
[End node1]
</xsl:template>
<xsl:template match="node2">
[Node2]:<xsl:value-of select="."></xsl:value-of>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="UTF-8"?>
[Node1]:node1.1
[Node2]:node2.1
[Node2]:node2.2
[End node1]
[Node2]:node2.1
[Node2]:node2.2
[Node1]:node1.2
[End node1]
As you can see template <xsl:template match="node2">
is applied twice for every node2 element - one time from node1 template and second time when XSLT processor is transforming node2 element.
Is there any solution to avoid applying of xsl:template match="node2"
second time?
I need to stop processing of node2 when I just processed it in template for node1.
Important This example is just an emulation of more complex use case. This means that we have additonal limitation - we can't modify template for root element processing.
I want to know if there is any way to stop processing of elements or move processing to some other elements.
You can use
mode
to name the template to use.You can create an empty catch-all node that will output nothing, taking care of
apply-templates
calls that have noselect
.The following stylesheet outputs what you need:
Note the empty modeless template at the end, and the added
mode
attribute on the template and the callingapply-templates
.XSLT doesn't track state and every apply-templates, for-each, etc will potentially produce "redundant" results, but this is entirely a problem in the design of the style-sheet - if you don't want to "process" a node more than once you need to change the appropriate templates and selects so it doesn't get handled more than once.
That would be fairly trivial for your example, but you said that your example isn't very representitive so I'd suggest you post something more complete if you're having problems.
This stylesheet:
Output:
Note: Two problems: you process
node2
more than once, fromroot
rule with applying templates to all node children, and fromnode1
rule; plus yourfollowing-sibling::node2
expression doesn't distinguish wichnode2
follows somenode1
.Edit: If you can't modify how
root
rule apply templates, then you would need modes for process and skip proccess: