Hi,
I have an xml file where I want to filter out all instances of a particular
element *except* those with specific attributes. I have got some XSLT that does
this.
Here is an example of the XML that needs filtered:
<resource>
<method href="ref1"/>
<method href="ref2"/>
<method href="ref3"/>
</resource>
And here is the XSLT that I am using:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="node()">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template
match="
/
| @*
| method[@href = 'ref1']
">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="method"/>
<xsl:template name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node() " />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When I use Saxon on the command line to transform the XML, I get this output:
<?xml version="1.0" encoding="UTF-8"?><resource>
<method href="ref1"/>
</resource>
Which is exactly what I want.
The first two templates are identical in terms of content, but if I try to
combine them into one template by combining their match attributes like this:
match="
/
| @*
| method[@href = 'ref1']
| node()
"
I get the following output
<?xml version="1.0" encoding="UTF-8"?><resource>
<method href="ref1"/>
<method href="ref2"/>
<method href="ref3"/>
</resource>
It looks like a priority issue – for some reason the node() match is higher
priority than the <xsl:template match="method"/> when it is included in the
other template, but not when it is in its own template.
I can’t see why this is happening. Section 6.4 of the spec
<https://www.w3.org/TR/xslt20/#conflict> says “If the pattern contains multiple
alternatives separated by | , then the template rule is treated equivalently to
a set of template rules, one for each alternative.” This implies to me that the
priority shouldn’t change just because node() is now included alongside the
other alternatives in a single match attribute.