Follow on question to: https://stackoverflow.com/questions/71635891/how-to-keep-track-of-position-from-a-template-to-a-different-template?noredirect=1#comment126614972_71635891
My new problem is, there could be more than one simplePath in a jump and I want all simplePath inside a jump to start
from the same position. My current is issue is that I'm not competent enough to translate my current idea into XSL, I added in comment in the XSLT code what I'm trying to achieve
D --- E --- F K --- L --- M --- N --- O
/ \ /
A --- B --- C--- / \ -- J ---/
\ / \
\ / \
G --- H --- I Q --- R --- S
<root>
<simplePath>
<point>A</point>
<point>B</point>
<point>C</point>
</simplePath>
<jump>
<simplePath>
<point>D</point>
<point>E</point>
<point>F</point>
</simplePath>
<simplePath>
<point>G</point>
<point>H</point>
<point>I</point>
</simplePath>
</jump>
<simplePath>
<point>J</point>
</simplePath>
</root>
expected output
A : 0
B : 50
C : 100
D : 300
E : 350
F : 400
Dbis : 300
Ebis : 350
Fbis : 400
G : 600
poor attempt :
<xsl:template match="/root">
<xsl:call-template name="process">
<xsl:with-param name="points" select=".//point"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="process">
<xsl:param name="points" />
<xsl:param name="total" select="0"/>
<xsl:param name="savePos" select="0"/>
<!-- new param -->
<!-- output -->
<xsl:value-of select="boolean($points[1]/ancestor::jump)"/>
<xsl:value-of select="$points[1]"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="$total"/>
<!-- recursive call -->
<xsl:if test="count($points) > 1">
<xsl:text>
</xsl:text>
<xsl:call-template name="process">
<xsl:with-param name="points" select="$points[position() > 1]"/>
<xsl:with-param name="total" select="if(boolean($points[1]/ancestor::jump) != boolean($points[2]/ancestor::jump)) then $total + 200 else $total + 50"/>
<!-- my "attempt" -->
<!-- I want to save the pos of total IF it's the first point of the first simplePath in a Jump -->
<xsl:with-param name="savePos" select=""/>
<!-- Next, I will add a new "if condition" here
<xsl:with-param name="total" select="if(boolean($points[1]/ancestor::jump) != boolean($points[2]/ancestor::jump))
then
>>>>if I'm not in the first simplePath of "jump", and it's the first "point" of this "simplePath" then
$total = $savePos
else
$total + 200
else
$total + 50"/>
- -->
</xsl:call-template>
</xsl:if>
</xsl:template>
I have the target /aggregate-rating.xml
<aggregate>
<rating>
<issuerNumber>388d</issuerNumber>
<WAABCA>baa1</WAABCA>
<WAABCANumeric>14.2</WAABCANumeric>
<WANotches>3.4</WANotches>
<WALTRatingNumeric>17.6</WALTRatingNumeric>
</rating>
<rating>
<issuerNumber>89f8</issuerNumber>
<WAABCA>b2</WAABCA>
<WAABCANumeric>7.4</WAABCANumeric>
<WANotches>-1.6</WANotches>
<WALTRatingNumeric>5.8</WALTRatingNumeric>
</rating>
===================================
</aggregate>
Mapping /rating-chart.xml
<ratings>
<rating MD="Aaa" SP="AAA" Grade="Investment" rank="1"/>
==================================
<rating MD="A1" SP="A+" Grade="Investment" rank="5"/>
<rating MD="A2" SP="A" Grade="Investment" rank="6"/>
<rating MD="A3" SP="A-" Grade="Investment" rank="7"/>
<rating MD="Baa1" SP="BBB+" Grade="Investment" rank="8"/>
========================
<rating MD="B2" SP="B" Grade="Non-Investment" rank="15"/>
<rating MD="B3" SP="B-" Grade="Non-Investment" rank="16"/>
<rating MD="Caa1" SP="CCC" Grade="Non-Investment" rank="17"/>
====================================
<rating MD="C" Grade="Non-Investment" rank="21"/>
</ratings>
The scale is based on WANotches. e.g issuer 388d, its WAABCA is baa1 (rank 8) then it notches 3.4 (round to 3), its rank is boosted to 5. The adjusted rating will be <rating MD="A1" SP="A+" Grade="Investment" rank="5"/>
Expected result:
<aggregate>
<rating>
<issuerNumber>388d</issuerNumber>
<WAABCA>baa1</WAABCA>
<WAABCANumeric>14.2</WAABCANumeric>
<WANotches>3.4</WANotches>
<WALTRatingNumeric>17.6</WALTRatingNumeric>
<adjustedMoody>A1</adjustedMoody>
<adjustedStandardPoor>A+</adjustedStandardPoor>
<adjustedGrade>Investment</adjustedGrade>
</rating>
<rating>
<issuerNumber>89f8</issuerNumber>
<WAABCA>b2</WAABCA>
<WAABCANumeric>7.4</WAABCANumeric>
<WANotches>-1.6</WANotches>
<WALTRatingNumeric>5.8</WALTRatingNumeric>
<adjustedMoody>Caa1</adjustedMoody>
<adjustedStandardPoor>CCC</adjustedStandardPoor>
<adjustedGrade>Non-Investment</adjustedGrade>
</rating>
=======================================
</aggregate>
My xsl:
<xsl:variable name="ratingChart" select="doc('/rating-chart.xml')"/>
<xsl:template match="rating">
<xsl:variable name="notch" select="round(WANotches)"/>
<xsl:variable name="currentRank" select="$ratingChart/ratings/rating[upper-case(#MD) eq upper-case(WAABCA)]/#rank"/>
<xsl:variable name="notchRank" select="$currentRank - $notch"/>
<xsl:variable name="aggRank" select="$ratingChart/ratings/rating[#rank = $notchRank]"/>
<xsl:variable name="adjustedMD" select="$aggRank/#MD"/>
<xsl:variable name="adjustedSP" select="$aggRank/#SP"/>
<xsl:variable name="adjustedGrade" select="$aggRank/#Grade"/>
<xsl:copy>
<xsl:sequence select="$aggRank"/>
<xsl:apply-templates/>
<xsl:call-template name="aggrRating">
<xsl:with-param name="aMD" select="$adjustedMD"/>
<xsl:with-param name="aSP" select="$adjustedSP"/>
<xsl:with-param name="aGrade" select="$adjustedGrade"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="aggrRating">
<xsl:param name="aMD"/>
<xsl:param name="aSP"/>
<xsl:param name="aGrade"/>
<adjustedMoody><xsl:value-of select="$aMD"/></adjustedMoody>
<adjustedStandardPoor><xsl:value-of select="$aSP"/></adjustedStandardPoor>
<adjustedGrade><xsl:value-of select="$aGrade"/></adjustedGrade>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
I got all the blank elements : <adjustedMoody>, <adjustedStandardPoor>, <adjustedGrade>.
How can I fix my xsl?
I have tried for hours to multiply 2 varibales in XSLT1 but I can't seem to figure it out.
The result shows in excel as NaN
I have searched for a while but I'm having trouble with this, just started using XSLT
Variables:
Weight = 10
Length = 12
XSLT:
<xsl:variable name ="content"><xsl:value-of select="$length * $weight" /></xsl:variable>
EDIT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rvmon="rosenbergverft.com:3D/2017/WeightMTO" xmlns:pdms="rosenbergverft.com:3D/2010/Models">
<xsl:output method="text" omit-xml-declaration="yes" standalone="no" media-type="text/xls" />
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." />
<xsl:template match="/">Building block;Discipline;Area;Sub. Area;Syst. no.;Weight Item no.;Piecemark no.;Weight Item Descr.;CompType;Type code;Rating or Scedule;Spec.;Dim. (");Material;Cost Code COR;Weight Phase Code;Mod. Phase Code;Weight Status % (allow.);Mod. Constr. Code;Mod. Handl. Code;No. off;Unit Length/ Area (m,m2, m3);Unit Weight (kg/m, m2, m3);Unit Weight MON(kg/m, m2, m3);Net Dry Weight (kg);Gross Dry Weight (kg);Content Weight (kg);Installed weight;CoG East;CoG North;CoG Elevation;Ref. doc., dwg., P&ID etc.;Remarks;Cost for instrument valves [NOK];install code;MON Lift Code;Paint Surface;Insulation Class;
<xsl:for-each select="/rvmon:WeightMTO/rvmon:MTOOwner"><xsl:for-each select="rvmon:Piecemark/rvmon:WeightItemNo/rvmon:Part">
<xsl:variable name= "weight" select="format-number(rvmon:ContentWeight/#number, '#0,0##', 'euro')" />
<xsl:variable name="length"><xsl:choose><xsl:when test="contains(rvmon:CompType,'BOLT')"><xsl:text> 1 </xsl:text></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000, '#0,0##', 'euro')" /></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm2'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000000, '#0,0##', 'euro')" /></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm3'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000000000, '#0,0##', 'euro')" /></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:UnitLength/#number, '#0,0##', 'euro')" /></xsl:otherwise></xsl:choose></xsl:variable>
<xsl:variable name="content" select="$length * $weight" />
<xsl:value-of select="../../../rvmon:BuildingBlock" />;<xsl:value-of select="rvmon:Discipline" />;<xsl:value-of select="../../../rvmon:Module" />;<xsl:value-of select="../../../rvmon:SubArea" />;<xsl:value-of select="../../../rvmon:SystNo" />;<xsl:value-of select="rvmon:WeightItemNo" />;<xsl:value-of select="rvmon:Piecemark" />;<xsl:value-of select="rvmon:WeightItemDescr" />;<xsl:value-of select="rvmon:CompType" />;<xsl:value-of select="rvmon:TypeCode" />;<xsl:value-of select="rvmon:Rating" />;<xsl:value-of select="rvmon:Spec" />;<xsl:choose><xsl:when test="rvmon:Discipline = 'L'"><xsl:value-of select="format-number(rvmon:Dim/#number, '#0,##', 'euro')" /><xsl:choose><xsl:when test="rvmon:Dim/#unit = 'inch'">"</xsl:when><xsl:otherwise><xsl:value-of select="rvmon:Dim/#unit" /></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="rvmon:Discipline = 'N'"></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:Dim/#number, '#0,##', 'euro')" /><xsl:value-of select="rvmon:Dim/#unit" /></xsl:otherwise></xsl:choose>;<xsl:value-of select="rvmon:Material" />;<xsl:value-of select="rvmon:CostCodeCOR" />;<xsl:value-of select="rvmon:WeightPhaseCode" />;<xsl:value-of select="rvmon:ModPhaseCode" />;<xsl:value-of select="format-number(rvmon:WeightStatus/#number * 100, '00', 'euro')" />%;<xsl:value-of select="rvmon:ModConstrCode" />;<xsl:value-of select="rvmon:ModHandlCode" />;<xsl:value-of select="format-number(rvmon:NoOff/#number, '#0,###', 'euro')" />;<xsl:value-of select="$length"/>;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="format-number(rvmon:UnitWeight/#number, '#0,0##', 'euro')" />;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="format-number(rvmon:MONUnitWeightFactor/#number, '#0,0#####', 'euro')" />;<xsl:choose><xsl:when test="contains(rvmon:CompType,'BOLT')"><xsl:text> 1 </xsl:text></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:NetDryWeight/#number, '#0,0##', 'euro')" /></xsl:otherwise></xsl:choose>;<xsl:value-of select="format-number(rvmon:AllowanceWeight/#number, '#0,0##', 'euro')" />;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="$weight"/>;<xsl:if test="rvmon:ProdStatus ='ABC' "><xsl:text> Yes </xsl:text></xsl:if>;<xsl:value-of select="format-number(rvmon:CoGEast/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="format-number(rvmon:CoGNorth/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="format-number(rvmon:CoGElevation/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="../../../rvmon:DrawNumber" />;<!-- xsl:value-of select="rvmon:Remarks" / --><xsl:value-of select="../../../pdms:PDMSElement/pdms:ElementName/#text" />;;;;<xsl:value-of select="format-number(rvmon:PaintSurface/#number div 1000000, '#0,0##', 'euro')" />;<xsl:value-of select="../../../rvmon:InsulationClass" />;<xsl:value-of select="$length"/>;<xsl:value-of select="$content"/><xsl:text>
</xsl:text></xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XML-document
<UnitLength number="1.000" unit="pcs" field="Quantity" />
<ContentWeight number="8.005" unit="kg" field="ContentWeight" /> />
I am able to output "weight" and "length" by itself. But I cant even do
"weight * 10"
Sorry if it is messy.
You need to remove all formatting number while assigning the variable and while multipled result need to format number like below:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:rvmon="rosenbergverft.com:3D/2017/WeightMTO"
exclude-result-prefixes="#all"
version="1.0">
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." />
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:variable name= "weight" select="//rvmon:ContentWeight/#number" />
<xsl:variable name="length">
<xsl:choose>
<xsl:when test="contains(//rvmon:CompType,'BOLT')">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000" />
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm2'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000000" />
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm3'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000000000" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//rvmon:UnitLength/#number" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="content" select="format-number(($weight * $length), '#0,0##', 'euro')" />
<xsl:value-of select="$content"/>
</xsl:template>
</xsl:stylesheet>
You have:
<xsl:variable name= "weight" select="format-number(rvmon:ContentWeight/#number, '#0,0##', 'euro')" />
A number formatted to use a decimal comma is no longer a number for the purposes of XPath/XSLT. A number can contain only digits and a decimal period.
Assuming that the original values (not shown in your question) are true numbers, use them for the multiplication, and format them only for the output.
I have following XML.
<?xml version="1.0" encoding="utf-8"?>
<ordersPack id="1398720518" ic="12345678" application="Web" version="2.0" note="user">
<orderPackItem id="2014042847">
<order>
<orderHeader>
<numberOrder>2014042847</numberOrder>
<partnerIdentity>
<billing>
<firstname>Ilona</firstname>
<surname>Kokerková</surname>
</billing>
</partnerIdentity>
</orderHeader>
<orderDetail>
<orderItem>
<name><![CDATA[Kokosový panenský olej 1000 ml]]></name>
<unitPriceWithTax>290.00</unitPriceWithTax>
</orderItem>
<orderItem>
<name><![CDATA[Dobírka ČP - Balík na poštu]]></name>
<quantity>1</quantity>
<percentVAT>21</percentVAT>
<unitPrice>86.78</unitPrice>
<unitPriceWithTax>105.00</unitPriceWithTax>
</orderItem>
</orderDetail>
<orderSummary>
</orderSummary>
</order>
</orderPackItem>
<orderPackItem id="2014042846">
<order>
<orderHeader>
<orderType>receivedOrder</orderType>
<partnerIdentity>
<billing>
<firstname>David</firstname>
<surname>Liala</surname>
</billing>
</partnerIdentity>
</orderHeader>
<orderDetail>
<orderItem>
<name><![CDATA[Mikula Bio Mladý ječmen prášek 250 g]]></name>
<unitPriceWithTax>469.00</unitPriceWithTax>
</orderItem>
<orderItem>
<name><![CDATA[osobní odběr Brno, Orlí 16, AWA centrum]]></name>
<unitPriceWithTax>0.00</unitPriceWithTax>
</orderItem>
</orderDetail>
<orderSummary>
</orderSummary>
</order>
</orderPackItem>
</ordersPack>
I need exclude all items with <dat:dataPackItem> if <inv:text>Hotově, osobní odběr</inv:text> contain "Hotově, osobní odběr".
And desire output is :
<?xml version="1.0" encoding="windows-1250"?>
<dat:dataPack id="fa002" ico="12345678" application="StwTest" version="2.0" note="FA" ">
<dat:dataPackItem id="2014042847" version="2.0">
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:invoiceType>issuedInvoice</inv:invoiceType>
</inv:accounting>
<inv:classificationVAT>
<typ:ids>UD</typ:ids>
</inv:classificationVAT>
<inv:partnerIdentity>
<typ:address>
<typ:company>firma</typ:company>
<typ:division>Obchodní oddělení</typ:division>
<typ:name>IlonaKokerková</typ:name>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>delivery</typ:paymentType>
</inv:paymentType>
<inv:account>
<typ:ids>KB</typ:ids>
</inv:account>
<inv:intNote>Faktura s textovou a skladovou položkou</inv:intNote>
</inv:invoiceHeader>
<inv:invoiceDetail>
<inv:invoiceItem>
<inv:text>Kokosový panenský olej 1000 ml</inv:text>
<inv:homeCurrency>
<typ:unitPrice>290.00</typ:unitPrice>
</inv:homeCurrency>
<inv:stockItem>
<typ:stockItem>
<typ:ids>awa1265</typ:ids>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
<inv:invoiceItem>
<inv:text>Dobírka zboží</inv:text>
<inv:homeCurrency>
<typ:unitPrice>0.00</typ:unitPrice>
</inv:homeCurrency>
<inv:stockItem>
<typ:stockItem>
<typ:ids></typ:ids>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
<inv:invoiceItem>
<inv:text>Dobírka ČP - Balík na poštu</inv:text>
<inv:homeCurrency>
<typ:unitPrice>105.00</typ:unitPrice>
</inv:homeCurrency>
<inv:stockItem>
<typ:stockItem>
<typ:ids></typ:ids>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
</inv:invoiceDetail>
</inv:invoice>
</dat:dataPackItem>
</dat:dataPack>
I need exclude all items with <dat:dataPackItem> if <inv:text>Hotově, osobní odběr</inv:text> contain "Hotově, osobní odběr".
How to do it?
Here is my XSLT....
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes" encoding="windows-1250" />
<xsl:template match="/">
<dat:dataPack id="fa002" ico="12345678" application="StwTest" version = "2.0" note="Import FA">
<xsl:for-each select="ordersPack/orderPackItem">
<dat:dataPackItem id="{order/orderHeader/numberOrder}" version="2.0">
<!-- faktura bez adresy s textovou a skladovou polozkou-->
<inv:invoice version="2.0">
<inv:invoiceHeader>
<inv:symVar>
<xsl:value-of select="order/orderHeader/numberOrder"/>
</inv:symVar>
<inv:numberOrder>
<xsl:value-of select="order/orderHeader/numberOrder"/>
</inv:numberOrder>
<inv:dateOrder>
<xsl:value-of select="order/orderHeader/dateFrom"/>
</inv:dateOrder>
<inv:partnerIdentity>
<typ:address>
<typ:company>firma</typ:company>
<typ:division>Obchodní oddělení</typ:division>
<typ:name>
<xsl:value-of select="order/orderHeader/partnerIdentity/billing/firstname"/>
<xsl:value-of select="order/orderHeader/partnerIdentity/billing/surname"/>
</typ:name>
</typ:address>
</inv:partnerIdentity>
<inv:paymentType>
<typ:paymentType>
<xsl:choose><xsl:when test="order/orderDetail/orderItem/name='Dobírka zboží'">delivery</xsl:when>
<xsl:otherwise>draft</xsl:otherwise></xsl:choose>
</typ:paymentType>
</inv:paymentType>
<inv:account>
<typ:ids>KB</typ:ids>
</inv:account>
<inv:note>Načteno z XML</inv:note>
<inv:intNote>Faktura s textovou a skladovou položkou</inv:intNote>
</inv:invoiceHeader>
<inv:invoiceDetail>
<!--skladova polozka-->
<xsl:for-each select="order/orderDetail/orderItem">
<inv:invoiceItem>
<inv:text>
<xsl:value-of select="name"/>
</inv:text>
<inv:quantity>
<xsl:value-of select="quantity"/>
</inv:quantity>
<inv:payVAT>true</inv:payVAT>
<xsl:choose>
<xsl:when test="percentVAT = '15'">
<inv:rateVAT>low</inv:rateVAT>
</xsl:when>
<xsl:when test="percentVAT = '21'">
<inv:rateVAT>high</inv:rateVAT>
</xsl:when>
</xsl:choose>
<inv:homeCurrency>
<typ:unitPrice>
<xsl:value-of select="unitPriceWithTax"/>
</typ:unitPrice>
</inv:homeCurrency>
<inv:stockItem>
<typ:stockItem>
<typ:ids>
<xsl:value-of select="product_nr"/>
</typ:ids>
</typ:stockItem>
</inv:stockItem>
</inv:invoiceItem>
</xsl:for-each>
</inv:invoiceDetail>
</inv:invoice>
</dat:dataPackItem>
</xsl:for-each>
</dat:dataPack>
</xsl:template>
</xsl:stylesheet>
You need to think in terms of the input, not the output. If you want to exclude all orderItem elements whose name includes "Hotově, osobní odběr" then you need to add a predicate to the orderItem for-each:
<!--skladova polozka-->
<xsl:for-each select="order/orderDetail/orderItem[not(contains(name, 'Hotově, osobní odběr'))]">
To completely remove any orderPackItem that contains any orderItem with this text you need the predicate at the top level:
<xsl:for-each select="ordersPack/orderPackItem[
not(order/orderDetail/orderItem[
contains(name, 'Hotově, osobní odběr')])]">
This is all about reverse a string. It works properly for the given Value 'ABCDEF'. The output is also correct 'FEDCBA'. But I want to know how this is printing letters 'A' and 'D' in this string. Could anyone help me to understand this? please.
Elaborate this working method.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="html"/>
<xsl:template name="reverse">
<xsl:param name="input" select="'ABCDEF'"/>
<xsl:variable name="len" select="string-length($input)"/>
<xsl:choose>
<xsl:when test="$len < 2">
<xsl:value-of select="$input"/>
</xsl:when>
<xsl:when test="$len = 2">
<xsl:value-of select="substring($input,2,1)"/>
<xsl:value-of select="substring($input,1,1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="mid" select="floor($len div 2)"/>
<xsl:call-template name="reverse">
<xsl:with-param name="input" select="substring($input,$mid+1,$mid+1)"/>
</xsl:call-template>
<xsl:call-template name="reverse">
<xsl:with-param name="input" select="substring($input,1,$mid)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="reverse">
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
Here's what happens:
Input ABCDEF
len = 6
len is > 2 and not = 2
mid = 3
Call again with input DEF
len = 3
len is > 2 and not = 2
mid = 1
Call again with input EF
len = 2
len is not > 2 but = 2
Put out the second letter F
Put out the first letter E
Return to outer call
Call with input = D
len is less than 2
Output D
Return to outer call
Call again with input = ABC
len = 3
len is > 2 and not 2
mid = 1
Call again with input BC
len = 2
len is not > 2 but = 2
Put out the second letter C
Put out the first letter B
Return to outer call
Call with input A
len is less than 2
Output A