Reputation: 316
I've struggled some time now. I just started with xslt, and I got things working just fine. Templates are used wherever possible and I've tried to keep myself from using for-loops.
My problem is this: I have a number of nodes with similar names, only difference is a postfix number from 1 to (currently) 5. These should all be transformed into a node without the numbers. So basically, here is what I have:
<title1>some title</title1>
<some_other_nodes>....</some_other_nodes>
<title2>some title2</title2>
.
.
.
<title5>....</title5>
And this is what I want:
<title>some title</title>
.
.
.
<title>some title2</title>
.
.
.
<title>....</title>
Is it possible to do substring matching with templates (matching just the title-part)?
Thanks for your help!
Upvotes: 2
Views: 3021
Reputation: 12729
For elements of the form titleN, where N is some number, use a match condition like ...
(corrected:)
<xsl:template match="*[starts-with(name(),'title')]
[number(substring(name(),6))=number(substring(name(),6))]">
etc...
Less generically, but quick and dirty, if you want SPECIFICALLY title1 through to title5, you might also think about ...
<xsl:template match="title1|title2|title3|title4|title5">
Upvotes: 2
Reputation: 243549
Here is a true XSLT 2.0 solution that covers even the most complex cases, not covered by other answers:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[matches(name(), '^title.*?\d+$')]">
<xsl:element name="{replace(name(), '^(title.*?)\d+$', '$1')}">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<title1>some title</title1>
<some_other_nodes>....</some_other_nodes>
<title2>some title2</title2> . . .
<title5>....</title5>
<titleX253>Complex title</titleX253>
</t>
the wanted, correct result is produced:
<t>
<title>some title</title>
<some_other_nodes>....</some_other_nodes>
<title>some title2</title> . . .
<title>....</title>
<titleX>Complex title</titleX>
</t>
Do note the element:
<titleX253>Complex title</titleX253>
It should be transformed into:
<titleX>Complex title</titleX>
This is not what the answer by Sean Durkin does !
Upvotes: 1