I have problem with matching.
I wanted like below at the end.
%3,00 CCC
%5,00 AAA
%3,00 CCC
%2,00 BBB
I got a help for it and have written somethings but got an error below if more than 1 invoiceline
.
Fatal Error: A sequence of more than one item is not allowed as the first argument of substring-after() ("11_003_AAA", "21_003_AAA", ...) A sequence of more than one item is not allowed as the first argument of substring-after() ("11_003_AAA", "21_003_AAA", ...)"
XML
<invoiceLine>
<ID>000011</ID>
<Note>40.00 BT</Note>
<Note>17_ 2005.00</Note>
<Note>11_005_AAA</Note>
<Note>11_002_BBB</Note>
<Note>11_003_CCC</Note>
<AllowanceCharge>
<MultiplierFactorNumeric>0.03</MultiplierFactorNumeric>
<Amount currencyID="USD">6.00</Amount>
</AllowanceCharge>
<AllowanceCharge>
<MultiplierFactorNumeric>0.05</MultiplierFactorNumeric>
</AllowanceCharge>
</invoiceLine>
<invoiceLine>
<ID>000021</ID>
<Note>10.00 CS</Note>
<Note>17_ 1005.00</Note>
<Note>21_005_AAA</Note>
<Note>21_002_BBB</Note>
<Note>21_003_CCC</Note>
<AllowanceCharge>
<MultiplierFactorNumeric>0.03</MultiplierFactorNumeric>
</AllowanceCharge>
<AllowanceCharge>
<MultiplierFactorNumeric>0.02</MultiplierFactorNumeric>
</AllowanceCharge>
</invoiceLine>
XSLT
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="2.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="note" match="./Note" use="substring-before(substring-after(., '_'), '_')" />
<xsl:template match="/invoiceline">
<xsl:for-each select="./AllowanceCharge/MultiplierFactorNumeric">
<xsl:text> %</xsl:text>
<xsl:value-of select="format-number(. * 100, '###.##0,00', 'european')"/>,
<xsl:value-of select="substring-after(substring-after(key('note', format-number(100 * ., '000')), '_'), '_')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
CodePudding user response:
First, your input is not a well-formed XML document. You must have a single root element - for example:
XML
<invoiceLines>
<invoiceLine>
<ID>000011</ID>
<Note>40.00 BT</Note>
<Note>17_ 2005.00</Note>
<Note>11_005_AAA</Note>
<Note>11_002_BBB</Note>
<Note>11_003_CCC</Note>
<AllowanceCharge>
<MultiplierFactorNumeric>0.03</MultiplierFactorNumeric>
<Amount currencyID="USD">6.00</Amount>
</AllowanceCharge>
<AllowanceCharge>
<MultiplierFactorNumeric>0.05</MultiplierFactorNumeric>
</AllowanceCharge>
</invoiceLine>
<invoiceLine>
<ID>000021</ID>
<Note>10.00 CS</Note>
<Note>17_ 1005.00</Note>
<Note>21_005_AAA</Note>
<Note>21_002_BBB</Note>
<Note>21_003_CCC</Note>
<AllowanceCharge>
<MultiplierFactorNumeric>0.03</MultiplierFactorNumeric>
</AllowanceCharge>
<AllowanceCharge>
<MultiplierFactorNumeric>0.02</MultiplierFactorNumeric>
</AllowanceCharge>
</invoiceLine>
</invoiceLines>
Now, if you want the key to work only within the current invoiceLine
, you must restrict it in some way. If you are able to use XSLT 2.0, then you can do it this way:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="note" match="Note" use="tokenize(., '_')[2]" />
<xsl:decimal-format name="european" decimal-separator="," grouping-separator="."/>
<xsl:template match="/invoiceLines">
<xsl:for-each select="invoiceLine">
<xsl:for-each select="AllowanceCharge">
<xsl:variable name="factor" select="100 * MultiplierFactorNumeric" />
<xsl:text> %</xsl:text>
<xsl:value-of select="format-number($factor, '#.##0,00', 'european')"/>
<xsl:text> </xsl:text>
<xsl:value-of select="tokenize(key('note', format-number($factor, '000'), ..), '_')[3]"/>
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
to get:
Result
%3,00 CCC
%5,00 AAA
%3,00 CCC
%2,00 BBB