Reputation: 1020
Is it possible in xslt to add new node between numbers and text within content text.
as example :
<doc>
<a>1 Available accessibility features for....</a>
<b>..between two teams of 11 players each on a..</b>
<c>The game is played by 120 million players..</c>
</doc>
I need to add <s>
node between numbers and text between above xml. so the output xml should be
<doc>
<a>1<s/> Available accessibility features for....</a>
<b>..between two teams of<s/> 11<s/> players each on a..</b>
<c>The game is played by <s/>120<s/> million players..</c>
</doc>
I tried hard find any method how can do this task but unable find any good solution. is there any possible way of do this in xslt ?
Upvotes: 1
Views: 123
Reputation: 122394
This is a simplification of Martin's answer. The way analyze-string
works is to split the input string into a sequence of matching and non-matching substrings and use the appropriate handler for each. Within a (non-)matching-substring handler, the position()
function is the position of this substring within the list of substring chunks and last()
is the total number of matching and non-matching substrings. Thus you can use a much simpler regex that just matches the digits, and use position()
to deal with the end effects:
<xsl:analyze-string select="." regex="[0-9]+">
<xsl:matching-substring>
<xsl:if test="position() gt 1">
<s/>
</xsl:if>
<xsl:value-of select="." />
<xsl:if test="position() lt last()">
<s/>
</xsl:if>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
The first if
is true if there was a non-matching substring before this matching substring, the second if
is true if there is at least one non-matching substring still to go following the current matching one (while it's not necessarily the case in general, for this particular regex we can guarantee that matching and non-matching substrings will strictly alternate. It's not possible to get two matching substrings next to each other with a greedy +
quantifier).
Upvotes: 1
Reputation: 167696
As already suggested, this is a job for analyze-string
. The stylesheet
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" priority="5">
<xsl:analyze-string select="." regex="(^|[^0-9]+)([0-9]+)([^0-9]+|$)">
<xsl:matching-substring>
<xsl:if test="string-length(regex-group(1)) gt 0">
<xsl:value-of select="regex-group(1)"/>
<s/>
</xsl:if>
<xsl:value-of select="regex-group(2)"/>
<xsl:if test="string-length(regex-group(3)) gt 0">
<s/>
<xsl:value-of select="regex-group(3)"/>
</xsl:if>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
transforms
<doc>
<a>1 Available accessibility features for....</a>
<b>..between two teams of 11 players each on a..</b>
<c>The game is played by 120 million players..</c>
</doc>
into
<doc>
<a>1<s/> Available accessibility features for....</a>
<b>..between two teams of <s/>11<s/> players each on a..</b>
<c>The game is played by <s/>120<s/> million players..</c>
</doc>
Upvotes: 3