Regular Expressions in xsl:template match attribute
I just want to know if it's possible to use regular expressions in the match
attribute of the xsl:template
element.
For example, suppose I have the follow XML document:
<greeting>
&开发者_StackOverflowlt;aaa>Hello</aaa>
<bbb>Good</bbb>
<ccc>Excellent</ccc>
<dddline>Line</dddline>
</greeting>
Now the XSLT to transform the above document:
<xsl:stylesheet>
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="matches(node-name(*),'line')">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
When I try to use the syntax matches(node-name(*),'line$')
in the match
attribute of the xsl:template
element, it retrieves a error message. Can I use regular expressions in the match
attribute?
Thanks very much
Here is the correct XSLT 1.0 way of matching (in XSLT 2.0 use the matches() function with a real RegEx as the pattern
argument):
Matching an element whose name contains 'line'
:
<xsl:template match="*[contains(name(), 'line')]">
<!-- Whatever processing is necessary -->
</xsl:template>
Matching an element whose name ends in 'line'
:
<xsl:template match="*[substring(name(), string-length() -3) = 'line']">
<!-- Whatever processing is necessary -->
</xsl:template>
@Tomalak provided another XSLT 1.0 way of finding names that end with a given string. His solution uses a special character that is guaranteed not to be ever present in any name. My solution can be applied to find if any string (not only a name of an element) ends with another given string.
In XSLT 2.x :
Use: matches(name(), '.*line$')
to match names that end with the string "line"
This transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*[matches(name(), '.*line$')]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="*[not(matches(name(), '.*line$'))]">
<xsl:apply-templates select="node()[not(self::text())]"/>
</xsl:template>
</xsl:stylesheet>
when applied on the XML document:
<greeting>
<aaa>Hello</aaa>
<bblineb>Good</bblineb>
<ccc>Excellent</ccc>
<dddline>Line</dddline>
</greeting>
Copies to the output only the element, whose name ends with the string "line"
:
<dddline>Line</dddline>
While this transformation (uses matches(name(), '.*line')
):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*[matches(name(), '.*line')]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="*[not(matches(name(), '.*line'))]">
<xsl:apply-templates select="node()[not(self::text())]"/>
</xsl:template>
</xsl:stylesheet>
copies to the output all elements, whose names contain the string "line"
:
<bblineb>Good</bblineb>
<dddline>Line</dddline>
In XSLT 1.0 (and 2.0, too), for your example (it's not a regex, though):
<xsl:template match="*[contains(name(), 'line')]">
<xsl:value-of select="."/>
</xsl:template>
and to achieve an end-of-string match:
<xsl:template match="*[contains(concat(name(), '
'), 'line
')]">
<xsl:value-of select="."/>
</xsl:template>
In XSLT 2.0 you can of course use the matches()
function in place of contains()
.
精彩评论