Outputting a list of elements - HELP

Here should go questions about transforming XML with XSLT and FOP.
aintnoprophet
Posts: 4
Joined: Thu Mar 22, 2007 6:42 pm

Outputting a list of elements - HELP

Post by aintnoprophet »

I have a collection of elements in xml that I need to process and output with xsl…

<Statement_Account_Charge>
<ChargeData>
<Charge>
< Date>3/28/07</ Date>
< Desc>First Charge</ Desc>
< Amt>$9.50</ Amt>
<Unit_Qty>1</ Unit_Qty>
< Unit_Amt>9.5000000</Amt>
</Charge>
</ChargeData>
<ChargeData>
<Charge>
< Date>3/28/07</ Date>
< Desc>Test Charge</ Desc>
< Amt>$11.50</ Amt>
<Unit_Qty>1</ Unit_Qty>
< Unit_Amt>11.5000000</Amt>
</Charge>
</ChargeData>
<ChargeData>
<Charge>
< Date>3/28/07</ Date>
< Desc>Test Charge</ Desc>
< Amt>$6.50</ Amt>
<Unit_Qty>1</ Unit_Qty>
< Unit_Amt>6.5000000</Amt>
</Charge>
</ChargeData>
<ChargeData>
<Charge>
< Date>3/28/07</ Date>
< Desc>Other Charge</ Desc>
< Amt>$7.50</ Amt>
<Unit_Qty>1</ Unit_Qty>
< Unit_Amt>7.5000000</Amt>
</Charge>
</ChargeData>

It looks like this except there are multiple /ChargeData/Charges. (There is only one charge per ChargeData)

I have several /Charges with a Desc of ‘Test Charge’.

Currently, I am outputting each /ChargeData/Charge to my pdf via xslt as a row.

I would like to modify this slightly to collect the /Charges with a Desc of ‘Test Charge’ and merge them into one row. The Date and Desc for each ‘Test Charge’ row are going to be the same. However, I would like to sum it’s Amt and Unit_Amt.


For Example (this is what I want the output to look like):
3/28/07 First Charge 9.5 x 1 $9.50
3/28/07 Test Charge 18.0 x 1 $18.00
3/28/07 First Charge 7.5 x 1 $7.50

Currently, I just loop through the /ChargeData/Charges with an xsl:for-each and output each as I come to it. I am at a loss on how to do this.

Can anyone give me some help on how I would accomplish this with xsl.

Thanks,
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Post by george »

Here it is an example. It uses XSLT 2.0 as it allows easily summing up the Amt values which are not numbers, in XSLT 1.0 you need to do that differently, for instance with a recursive template.

Note also that your sample input is not XML wellformed.

Code: Select all


<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="Statement_Account_Charge">
<result>
<xsl:apply-templates select="*"/>
</result>
</xsl:template>

<xsl:template match="ChargeData">
<line>
<xsl:value-of select="Charge/Date"/>
<xsl:text> </xsl:text>
<xsl:value-of select="Charge/Desc"/>
<xsl:text> </xsl:text>
<xsl:value-of select="Charge/Unit_Amt"/>
<xsl:text>x</xsl:text>
<xsl:value-of select="Charge/Unit_Qty"/>
<xsl:text> </xsl:text>
<xsl:value-of select="Charge/Amt"/>
</line>
</xsl:template>
<xsl:template match="ChargeData[Charge/Desc='Test Charge']"/>
<xsl:template match="ChargeData[Charge/Desc='Test Charge'][not(preceding-sibling::ChargeData[Charge/Desc='Test Charge'])]" priority="10">
<line>
<xsl:value-of select="Charge/Date"/>
<xsl:text> </xsl:text>
<xsl:value-of select="Charge/Desc"/>
<xsl:text> </xsl:text>
<xsl:value-of select="sum(../ChargeData[Charge/Desc='Test Charge']/Charge/Unit_Amt)"/>
<xsl:text>x</xsl:text>
<xsl:value-of select="Charge/Unit_Qty"/>
<xsl:text> $</xsl:text>
<xsl:value-of select="sum(../ChargeData[Charge/Desc='Test Charge']/Charge/number(substring-after(Amt, '$')))"/>
</line>
</xsl:template>
</xsl:stylesheet>
Best Regards,
George
George Cristian Bina
aintnoprophet
Posts: 4
Joined: Thu Mar 22, 2007 6:42 pm

Post by aintnoprophet »

<xsl:value-of select="sum(../ChargeData[Charge/Desc='Test Charge']/Charge/number(substring-after(Amt, '$')))"/>
It seems as though it doesn't like this part.

It gives me the following error.

NodeTest expected here. sum(../ChargeData[Charge/Desc='Test Charge']/Charge/-->number<--(substring-after(Amt, '$')))

It could possibly be my implementation of this example...however, I pretty much copied what you posted...slightly modified...the xml to be well-formed just so I could see what it would do...the error then presented itself.

I am not sure what to do.

Thank you for all your help.

jc
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Post by george »

You need to use an XSLT 2.0 processor, Saxon 8 for instance. In oXygen make sure you select that as the XSLT processor for your transformation.
As I said, in XSLT 1.0 you probably need to write a recursive template to compute that sum.

Best Regards,
George
George Cristian Bina
aintnoprophet
Posts: 4
Joined: Thu Mar 22, 2007 6:42 pm

Post by aintnoprophet »

In the end I won't be running it under oXygen...and I will have to assume that the program i'm using is not going to support a XSLT 2.0 processor.

Do you have a basic example of how to write a recursive template or perhaps point me in the direction of one?

I'll search on my own in the meantime. I am fairly new to xslt and am getting forced into advanced (in my opinion) applications of it.

Thanks again.

jc
Post Reply