Convert 24 hour time to 12 hour time in XSLT - xslt

Converting the hour seems to take a lot of work... there must be a simpler way.
<xsl:variable name="hour12">
<xsl:choose>
<xsl:when test="$hour24 < 0">
<xsl:value-of select="12 + $hour24" />
</xsl:when>
<xsl:when test="$hour24 = 0">
<xsl:value-of select="12" />
</xsl:when>
<xsl:when test="$hour24 = 12">
<xsl:value-of select="$hour24" />
</xsl:when>
<xsl:when test="$hour24 > 12">
<xsl:value-of select="$hour24 - 12" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$hour24" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Any suggestions?

Oh...I love how boolean values equal 0 or 1. It makes life so much easier...
<xsl:variable name="hour12">
<xsl:value-of select="$hour24 - (12 * ($hour24 > 12)) + (12 * ($hour24 = 0))" />`
</xsl:variable>
And for the a/p identifier
<xsl:variable name="ap">
<xsl:value-of select="substring('ap', 1 + ($hour24 >= 12), 1)" />
</xsl:variable>

For the time conversion, here is something which I find simpler:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="time/text()">
<xsl:variable name="vZ" select="(.+12) mod 12"/>
<xsl:value-of select="$vZ - ($vZ -12)*($vZ=0)"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t>
<time>-3</time>
<time>0</time>
<time>7</time>
<time>12</time>
<time>17</time>
<time>24</time>
</t>
the wanted, correct result is produced:
<t>
<time>9</time>
<time>12</time>
<time>7</time>
<time>12</time>
<time>5</time>
<time>12</time>
</t>
For am/pm (if my understanding for the edge cases is correct) we add this code:
<xsl:variable name="vNorm" select=
"not(. >= 0)*(24 +.)
+
(. >=0 and not(. = 24))*.
+
not(. = 24)
"/>
<xsl:value-of select="$vPeriods[1+($vNorm>=12)]"/>
The complete transformation becomes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:timePeriods>
<p>am</p>
<p>pm</p>
</my:timePeriods>
<xsl:variable name="vPeriods" select=
"document('')/*/my:timePeriods/*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="time/text()">
<xsl:variable name="vZ" select="(.+12) mod 12"/>
<xsl:value-of select="$vZ - ($vZ -12)*($vZ=0)"/>
<xsl:variable name="vNorm" select=
"not(. >= 0)*(24 +.)
+
(. >=0 and not(. = 24))*.
+
not(. = 24)
"/>
<xsl:value-of select="$vPeriods[1+($vNorm>=12)]"/>
</xsl:template>
</xsl:stylesheet>
and when applied to the same XML document (above) the result is:
<t>
<time>9pm</time>
<time>12am</time>
<time>7am</time>
<time>12pm</time>
<time>5pm</time>
<time>12am</time>
</t>

Related

How to create a composite key for muenchian grouping

These are just three records of my client's xml, but it shows the problem:
<Export>
<Record>
<JournalX>01-252-5390</JournalX>
<PositionX></PositionX>
<DepartmentX></DepartmentX>
<Description><![CDATA[UK - Take The Cash]]></Description>
<Amount>116.66</Amount>
<PayDate>06/30/2022</PayDate>
<PPEndDate>06/30/2022</PPEndDate>
</Record>
<Record>
<JournalX>5200</JournalX>
<PositionX></PositionX>
<DepartmentX>262</DepartmentX>
<Description><![CDATA[UK - Salary]]></Description>
<Amount>3655.92</Amount>
<PayDate>06/30/2022</PayDate>
<PPEndDate>06/30/2022</PPEndDate>
</Record>
<Record>
<JournalX>5200</JournalX>
<PositionX>311</PositionX>
<DepartmentX>310</DepartmentX>
<Description><![CDATA[UK - Salary]]></Description>
<Amount>1424.99</Amount>
<PayDate>06/30/2022</PayDate>
<PPEndDate>06/30/2022</PPEndDate>
</Record>
</Export>
What needs to happen is to sum Amount by Description and AcctNo. As you can see there is not AcctNo in the XML. This is how I created an AcctNo variable:
<xsl:variable name="AcctNo">
<xsl:choose>
<xsl:when test="string-length(JournalX) > 4">
<xsl:value-of select="JournalX" />
</xsl:when>
<xsl:when test="string-length(PositionX) != 3 or PositionX = '' ">
<xsl:value-of select="concat('01-', DepartmentX, '-', JournalX)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('01-', PositionX, '-', JournalX)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Alternatively, I created an AcctNo function in the CData section, basically the same algorithm. But the problem with either of these, is that I have to create the Key outside the template definition and the variable is defined within the template, therefore not available to the variable.
An additional problem, at least I think it may be, is that they want the output to be csv.
Can anyone help me? Thank You so much, Greg
I have copied code I found on the web and tried to modify it which is how I found out about the limitation.
Any help would be really appreciated.
Using XSLT 3 with
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="text" indent="yes" html-version="5"/>
<xsl:template match="/Export">
<xsl:for-each-group select="Record" composite="yes" group-by="Description, if (string-length(JournalX) > 4) then JournalX else if (string-length(PositionX) != 3 or PositionX = '') then concat('01-', DepartmentX, '-', JournalX) else concat('01-', PositionX, '-', JournalX)">
<xsl:value-of select="sum(current-group()/Amount)"/>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
I get
116.66
3655.92
1424.99
using XSLT 1.0 with a two step transformation I get the same result
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output method="text" indent="yes" />
<xsl:key name="group-by-desc-and-acctno" match="Record" use="concat(Description, '|', AcctNo)"/>
<xsl:template match="/Export">
<xsl:variable name="records-with-added-acctno-rtf">
<xsl:apply-templates select="Record"/>
</xsl:variable>
<xsl:variable name="records-with-added-acctno" select="exsl:node-set($records-with-added-acctno-rtf)/Record"/>
<xsl:for-each select="$records-with-added-acctno[generate-id() = generate-id(key('group-by-desc-and-acctno', concat(Description, '|', AcctNo))[1])]">
<xsl:value-of select="sum(key('group-by-desc-and-acctno', concat(Description, '|', AcctNo))/Amount)"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="Record">
<xsl:copy>
<xsl:copy-of select="*"/>
<AcctNo>
<xsl:choose>
<xsl:when test="string-length(JournalX) > 4">
<xsl:value-of select="JournalX" />
</xsl:when>
<xsl:when test="string-length(PositionX) != 3 or PositionX = '' ">
<xsl:value-of select="concat('01-', DepartmentX, '-', JournalX)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('01-', PositionX, '-', JournalX)"/>
</xsl:otherwise>
</xsl:choose>
</AcctNo>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Is it possible to provide a few values for the same param in XSL (vararg)?

I'm trying to create an XSL 2.0 template, which I would be able to call with a few <xsl:with-param/> values, all of them bound to the same <xsl:param>. In other words, I'm looking for a variadic template or its best alternative. Can you suggest some?
ps. This is what I came up with:
<xsl:template name="i">
<xsl:param name="args"/>
<xsl:for-each select="$args/*">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
Then, I'm calling it like this:
<xsl:template match="f">
<xsl:call-template name="i">
<xsl:with-param name="args"/>
<a><xsl:value-of select="./#one"/></a>
<a><xsl:value-of select="./#two"/></a>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
There are many ways to do this, below are just three of them:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pParams" select="3,5,15,22,7"/>
<xsl:param name="pParams2" select="'3,5,15,22,7'"/>
<xsl:param name="pParams3" select="/*/*[1], /*/*[2], /*/*[3] "/>
<xsl:template match="/*">
<xsl:for-each select="$pParams">
<xsl:sequence select=". * 2"/>
</xsl:for-each>
<xsl:value-of select="'
'"/>
<xsl:for-each select="tokenize($pParams2, ',')">
<xsl:sequence select="number(.) * 2"/>
</xsl:for-each>
<xsl:value-of select="'
'"/>
<xsl:for-each select="$pParams3">
<xsl:sequence select="name(.)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on this XML document:
<t>
<a/>
<b/>
<c/>
</t>
the wanted result is produced:
6 10 30 44 14
6 10 30 44 14
a b c

XSLT to handle quotes and Pipe Delimited symbol

Experts, i need to write XSLT 1.0 code to remove the quotes for multiple conditions.
CASE1: Remove the double quotes
CASE2: Remove the double quotes + delete the PIPE symbol inside that double quotes (IF exist)
CASE3: Remove Single quote " from the input field.
Input:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ns0:Accounting xmlns:ns0="http://sample.com">
<Record>
<DRCR>"DR"</DRCR>
<GLREFERENCE>"TEST|CASE"</GLREFERENCE>
<GLVALUEDATE>EXAM"PLE</GLVALUEDATE>
<GLACCOUNTNUMBER>"1160</GLACCOUNTNUMBER>
<GLEXAMPLE>123</GLEXAMPLE>
<GLEXAMPLE1>EXTRACT|2021-06-16|2853|1308026.7500|1176</GLEXAMPLE1>
</Record>
</ns0:Accounting>
** Desired Output:**
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ns0:Accounting xmlns:ns0="http://sample.com">
<Record>
<DRCR>DR</DRCR>
<GLREFERENCE>TEST CASE</GLREFERENCE>
<GLVALUEDATE>EXAMPLE</GLVALUEDATE>
<GLACCOUNTNUMBER>1160</GLACCOUNTNUMBER>
<GLEXAMPLE>123</GLEXAMPLE>
<GLEXAMPLE1>EXTRACT|2021-06-16|2853|1308026.7500|1176</GLEXAMPLE1>
</Record>
</ns0:Accounting>
** XSLT I tried:**
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:call-template name="process">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="process">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '"')">
<xsl:value-of select="substring-before($text, '"')"/>
<xsl:value-of select="translate(substring-before(substring-after($text, '"'), '"'), '|', '')"/>
<xsl:call-template name="process">
<xsl:with-param name="text" select="substring-after(substring-after($text, '"'), '"')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This XSLT not handling case 3, which has single quote in the input field. Please assist here..
Maybe something like this could work for you:
XSLT 1.0 (+ EXSLT node-set function)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:choose>
<xsl:when test="contains(., '"')">
<xsl:variable name="tokens">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="exsl:node-set($tokens)/token">
<xsl:choose>
<xsl:when test="(position()=1 or position()=last()) and last() > 1">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(., '|', '')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="'"'"/>
<xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
<xsl:if test="$token">
<token>
<xsl:value-of select="$token"/>
</token>
</xsl:if>
<xsl:if test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Note that this does not check the parity of the quotation marks. Any vertical bar character that is both preceded and followed by a quotation mark will be removed. For example, an input of:
<EXAMPLE>abc|123"def|456"ghi|789"jkl|012</EXAMPLE>
will be transformed to:
<EXAMPLE>abc|123def456ghi789jkl|012</EXAMPLE>

looping number to get sequence

Input XML:
<root>
<number>4</number>
<format>start1</format>
<!--this could be start0/start1/alpha -->
</root>
My output should be:
If format=start1 Print 1,2,3,4
If format=start0 Print 0,1,2,3
If format=alpha Print A,B,C,D
number of sequential items is equal to value of "number" node
XSLT stub:
<xsl:template match="/">
<xsl:variable name="mynumber" select="number"></xsl:variable>
<xsl:variable name="mysequence">
<xsl:choose>
<xsl:when test="format='start0'">
<xsl:for-each select="$mynumber">
<!--0,1,2,3-->
</xsl:for-each>
</xsl:when>
<xsl:when test="format='start1'">
<xsl:for-each select="$mynumber">
<!--1,2,3,4-->
</xsl:for-each>
</xsl:when>
<xsl:when test="format='alpha'">
<xsl:for-each select="$mynumber">
<!--A, B, C, D-->
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$mysequence"></xsl:value-of>
</xsl:template>
Consider the following example:
XML
<root>
<item>
<number>4</number>
<format>start0</format>
</item>
<item>
<number>4</number>
<format>start1</format>
</item>
<item>
<number>4</number>
<format>alpha</format>
</item>
</root>
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<sequence>
<xsl:choose>
<xsl:when test="format='start0'">
<xsl:value-of select="for $i in 1 to number return $i - 1" separator=", "/>
</xsl:when>
<xsl:when test="format='start1'">
<xsl:value-of select="for $i in 1 to number return $i" separator=", "/>
</xsl:when>
<xsl:when test="format='alpha'">
<xsl:value-of select="for $i in 1 to number return codepoints-to-string($i + 64)" separator=", "/>
</xsl:when>
</xsl:choose>
</sequence>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<sequence>0, 1, 2, 3</sequence>
<sequence>1, 2, 3, 4</sequence>
<sequence>A, B, C, D</sequence>
</root>
Note that this assumes number will not exceed 26 (at least not when the format is "alpha"); otherwise you will need to use xsl:number to format it as alpha, as shown in the answer by #potame - except it could be more concise:
<xsl:template match="item">
<xsl:variable name="fmt" select="format" />
<sequence>
<xsl:for-each select="1 to number">
<xsl:number value="if ($fmt='start0') then . - 1 else ." format="{if ($fmt='alpha') then 'A' else '0'}"/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</sequence>
</xsl:template>
Here's a possible solution, thanks to the use of an XPath sequence, e.g. select="1 to 10":
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="html" doctype-public="XSLT-compat"
omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="root">
<xsl:variable name="mynumber" select="number" as="xs:integer" />
<xsl:variable name="mysequence">
<xsl:choose>
<xsl:when test="format='start0'">
<xsl:for-each select="0 to ($mynumber - 1)">
<!--0,1,2,3-->
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:when>
<xsl:when test="format='start1'">
<xsl:for-each select="1 to $mynumber">
<!--0,1,2,3-->
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:when>
<xsl:when test="format='alpha'">
<xsl:for-each select="1 to $mynumber">
<xsl:number value="." format="A"/>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$mysequence"/>
</xsl:template>
</xsl:transform>

Create a recursive string function for adding a sequence

I've a challenging problem and so far I wasn't able to solve.
Within my xlst I have variable which contains a string.
I need to add the following sequence [eol] to this string.
On a fix position namely every 65 characters
I thought to use a function or template to recursive add this charackter.
The reason is that the string length can variate in length.
<xsl:function name="funct:insert-eol" as="xs:string" >
<xsl:param name="originalString" as="xs:string?"/>
<xsl:variable name="length">
<xsl:value-of select="string-length($originalString)"/>
</xsl:variable>
<xsl:variable name="start" as="xs:integer">
<xsl:value-of select="1"/>
</xsl:variable>
<xsl:variable name="eol" as="xs:integer">
<xsl:value-of select="65"/>
</xsl:variable>
<xsl:variable name="newLines">
<xsl:value-of select="$length idiv number('65')"/>
</xsl:variable>
<xsl:for-each select="1 to $newLines">
<xsl:value-of select="substring($originalString, $start, $eol)" />
</xsl:for-each>
</xsl:function>
The more I write code the more variables I need to introduce. This is still my lack on understanding.
For example we want every 5 chars an [eol]
aaaaaaabbbbbbccccccccc
aaaaa[eol]aabbb[eol]bbbcc[eol]ccccc[eol]cc
Hope someone has a starting point for me..
Regards Dirk
Rather straight-forward and short -- no recursion is necessary (and can even be specified as a single XPath expression):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="pLLength" select="5"/>
<xsl:template match="/*">
<xsl:variable name="vText" select="string()"/>
<xsl:for-each select="1 to string-length($vText) idiv $pLLength +1">
<xsl:value-of select="substring($vText, $pLLength*(position()-1)+1, $pLLength)"/>
<xsl:if test=
"not(position() eq last()
or position() eq last() and string-length($vText) mod $pLLength)">[eol]</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on this XML document:
<t>aaaaaaabbbbbbccccccccc</t>
the wanted, correct result is produced:
aaaaa[eol]aabbb[eol]bbbcc[eol]ccccc[eol]cc
When this XML document is processed:
<t>aaaaaaabbbbbbcccccccccddd</t>
again the wanted, correct result is produced:
aaaaa[eol]aabbb[eol]bbbcc[eol]ccccc[eol]ccddd[eol]
You can treat it as a grouping problem, using for-each-group:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:function name="mf:insert-eol" as="xs:string">
<xsl:param name="input" as="xs:string"/>
<xsl:param name="chunk-size" as="xs:integer"/>
<xsl:value-of>
<xsl:for-each-group select="string-to-codepoints($input)" group-by="(position() - 1) idiv $chunk-size">
<xsl:if test="position() gt 1"><xsl:sequence select="'eol'"/></xsl:if>
<xsl:sequence select="codepoints-to-string(current-group())"/>
</xsl:for-each-group>
</xsl:value-of>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text">
<xsl:copy>
<xsl:sequence select="mf:insert-eol(., 5)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
That stylesheet transforms
<root>
<text>aaaaaaabbbbbbccccccccc</text>
</root>
into
<root>
<text>aaaaaeolaabbbeolbbbcceolccccceolcc</text>
</root>
Try this one:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:param name="TextToChange" select="'aaaaaaabbbbbbccccccccc'"/>
<xsl:param name="RequiredLength" select="xs:integer(5)"/>
<xsl:template match="/">
<xsl:call-template name="AddText"/>
</xsl:template>
<xsl:template name="AddText">
<xsl:param name="Text" select="$TextToChange"/>
<xsl:param name="TextLength" select="string-length($TextToChange)"/>
<xsl:param name="start" select="xs:integer(1)"/>
<xsl:param name="end" select="$RequiredLength"/>
<xsl:choose>
<xsl:when test="$TextLength gt $RequiredLength">
<xsl:value-of select="substring($Text,$start,$end)"/>
<xsl:text>[eol]</xsl:text>
<xsl:call-template name="AddText">
<xsl:with-param name="Text" select="substring-after($Text, substring($Text,$start,$end))"/>
<xsl:with-param name="TextLength"
select="string-length(substring-after($Text, substring($Text,$start,$end)))"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>