I have next xml:
<page>
<document>
<id>1001</id>
<cur>USD</cur>
<date>01.01.2009</date>
<amount>10</amount>
</document>
<document>
<id>1001</id>
<cur>USD</cur>
<date>02.01.2009</date>
<amount>15</amount>
</document>
<document>
<id>1001</id>
<cur>JPY</cur>
<date>01.01.2009</date>
<amount>5</amount>
</document>
<document>
<id>1002</id>
<cur>USD</cur>
<date>01.01.2009</date>
<amount>5</amount>
</document>
...
</page>
And I need to transform it into html. Records should be grouped by id and cur. And after each group total amount should be shown. So we want something like this:
Bill: id=1001, cur=USD
date=01.01.2009 amount=10
date=02.01.2009 amount=15
total amount=25
Bill: id=1001, cur=JPY
date=01.01.2009 amount=5
total amount=5
Bill: id=1002, cur=USD
date=01.01.2009 amount=5
total amount=5
...
How can I achieve this using XSL?
When I tried to find answer in google I found Muenchian method, but it's too complicated when we want to group result by 2 fields. I'm beginner in xsl and it's a bit difficult to me. I also found xslt 2.0 operator for-each-group. Is it supported by major browsers? Is it normally to use it or we should only rely on xslt 1.0?
Returns the contents of the current group selected by xsl:for-each-group. Available in XSLT 2.0 and later versions. Available in all Saxon editions. current-group() ➔ item()*
Specifies the format pattern. Here are some of the characters used in the formatting pattern: 0 (Digit) # (Digit, zero shows as absent)
contains() Function — Determines if the first argument string contains the second.
You can do this with XSLT 1.0
The method i use here is to create a composite key with the two fields, id and cur. I later apply the templates to the first document in each group. Within the template i then loop through the individual documents and finally i summarize the documents amount field.
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="idcur" match="document" use="concat(id,cur)"/>
<xsl:template match="/page">
<xsl:apply-templates select="document[generate-id() = generate-id(key('idcur',concat(id,cur))[1])]"/>
</xsl:template>
<xsl:template match="document">
<xsl:variable name="document" select="key('idcur',concat(id,cur))"/>
Bill: id=<xsl:value-of select="id"/>, cur=<xsl:value-of select="cur"/>
<xsl:for-each select="$document">
date=<xsl:value-of select="date"/> amount=<xsl:value-of select="amount"/>
</xsl:for-each>
total amount=<xsl:value-of select="sum($document/amount)"/>
</xsl:template>
</xsl:stylesheet>
Output:
Bill: id=1001, cur=USD
date=01.01.2009 amount=10
date=02.01.2009 amount=15
total amount=25
Bill: id=1001, cur=JPY
date=01.01.2009 amount=5
total amount=5
Bill: id=1002, cur=USD
date=01.01.2009 amount=5
total amount=5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With