Page 1 of 1

Outputting a list of elements - HELP

Posted: Thu May 17, 2007 12:42 am
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,

Posted: Thu May 17, 2007 9:53 am
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

Posted: Thu May 17, 2007 5:53 pm
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

Posted: Thu May 17, 2007 5:58 pm
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

Posted: Thu May 17, 2007 6:06 pm
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