Regular expressions in xsl: template matching attribute

I just want to know if regular expressions can be used in the match attribute of an xsl:template element. For example, suppose I have the following XML document:

 <greeting> <aaa>Hello</aaa> <bbb>Good</bbb> <ccc>Excellent</ccc> <dddline>Line</dddline> </greeting> 

XSLT now converts 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 receives an error message. Can regular expressions be used in the match attribute?

Many thanks

+6
xml regex xpath xslt
source share
2 answers

Here is the correct way to map XSLT 1.0 (in XSLT 2.0, use the matches () function with the real RegEx as the pattern argument):

Correspondence of the element whose name contains 'line' :

 <xsl:template match="*[contains(name(), 'line')]"> <!-- Whatever processing is necessary --> </xsl:template> 

Correspondence of the element whose name ends with 'line' :

 <xsl:template match="*[substring(name(), string-length() -3) = 'line']"> <!-- Whatever processing is necessary --> </xsl:template> 

@Tomalak provided another way to search for XSLT 1.0 that ends with the given string. His decision uses a special character that is guaranteed not to be present in any name. My solution can be applied to search if any line (and not just the element name) ends with another given line.

In XSLT 2.x :

Use : matches(name(), '.*line$') to match names ending with "line"

This conversion is :

when applied to theis XML document :

 <greeting> <aaa>Hello</aaa> <bblineb>Good</bblineb> <ccc>Excellent</ccc> <dddline>Line</dddline> </greeting> 

Only the element whose name ends with the line is copied to the output :

 <dddline>Line</dddline> 

So far this is a conversion (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 the elements whose names contain the string "line" :

 <bblineb>Good</bblineb> <dddline>Line</dddline> 
+14
source share

In XSLT 1.0 (and 2.0 too) for your example (this is not a regular expression):

 <xsl:template match="*[contains(name(), 'line')]"> <xsl:value-of select="."/> </xsl:template> 

and to achieve the end of line match:

 <xsl:template match="*[contains(concat(name(), '&#xA;'), 'line&#xA;')]"> <xsl:value-of select="."/> </xsl:template> 

In XSLT 2.0, you can of course use matches() instead of contains() .

+5
source share

All Articles