Transforming with XSLT, Grouping elements until difference found.

J

Jody Greening

Transforming with XSLT, Grouping elements until difference found.

I am seeking some help with the following problem, I am fairly new at
XSLT transformations, and my problem may lie in looking at it from a
traditional programming point of view.

I have did quite a bit of searching but have found no answers to my
particular problem... please read below XML for the problem I am
having.

PS: I have no control over the XML I am trying to transform.

--- I have only spaced the lines for clarity ---

<Amounts>
<Amount date="2004-05-30">5290</Amount>
<Amount date="2004-06-30">5290</Amount>

<Amount date="2004-07-30">5300</Amount>
<Amount date="2004-08-30">5300</Amount>

<Amount date="2004-09-30">5290</Amount>
<Amount date="2004-10-30">5290</Amount>
<Amount date="2004-11-30">5290</Amount>

<Amount date="2004-12-30">1000</Amount>

<Amount date="2005-01-30">5290</Amount>

<Amount date="2005-02-28">5300</Amount>

<Amount date="2005-03-30">5290</Amount>
<Amount date="2005-04-30">5290</Amount>

<Amount date="2004-07-30">5300</Amount>
<Amount date="2004-08-30">5300</Amount>
</Amounts>

I am looking to transform the above XML into the below structure
grouping payments with alike ones util there is a different payment
encountered. I also need to inculde a count of the like payments.

Output should look like this: (in the correct order found in the input
stream) I have had limited success with for-each but the problem lies
in the counting of the LIKE elements.

<Payments>
<Payment amount="5290" numpayments="2" />
<Payment amount="5300" numpayments="2" />
<Payment amount="5290" numpayments="3" />
<Payment amount="1000" numpayments="1" />
<Payment amount="5290" numpayments="1" />
<Payment amount="5300" numpayments="1" />
<Payment amount="5290" numpayments="2" />
<Payment amount="5300" numpayments="2" />
</Payments>

Any help would be greatly appreciated.
Jody Greening
jgreening#AT#cyence#DOT#com
 
M

Martin Honnen

Jody said:
Transforming with XSLT, Grouping elements until difference found.

I am seeking some help with the following problem, I am fairly new at
XSLT transformations, and my problem may lie in looking at it from a
traditional programming point of view.

I have did quite a bit of searching but have found no answers to my
particular problem

Grouping is described here:
<http://www.jenitennison.com/xslt/grouping/index.html>
 
J

Jody Greening

I have already looked through those examples, but I did not find
anything that can answer my above question. Maybe I am not seeing it,
but there is no example there of what I am trying to accomplish.

I have figured out a way to lop and see if the current value is the
same as the previous, but I am still having the problem of counting
them.

Keep in mind that the outputs here are strictly for testing purposes.

<xsl:template match="Results/Stream[@name='Rents']/Amounts/Amount">
<xsl:for-each select="." >
<xsl:variable name="PreviousAmount"
select="preceding-sibling::Amount[position()=1]" />
<xsl:variable name="CurrentAmount" select="." />
<xsl:choose>
<xsl:when test="scripts:CheckIfNull($CurrentAmount, '0') =
scripts:CheckIfNull($PreviousAmount, '0')">
<TransPaymentInfo>
<xsl:attribute name="TransSubScheduleId">
<xsl:text>Same as last one </xsl:text>
| Current Payment - <xsl:value-of
select="scripts:CheckIfNull($CurrentAmount, 'BLANK')" />
| Previous Payment - <xsl:value-of
select="scripts:CheckIfNull($PreviousAmount, 'BLANK')" />
</xsl:attribute>
</TransPaymentInfo>
</xsl:when>
<xsl:eek:therwise>
<TransPaymentInfo>
<xsl:attribute name="TransSubScheduleId">
<xsl:text>Different than last one </xsl:text>
| Current Payment - <xsl:value-of
select="scripts:CheckIfNull($CurrentAmount, 'BLANK')" />
| Previous Payment - <xsl:value-of
select="scripts:CheckIfNull($PreviousAmount, 'BLANK')" />
</xsl:attribute>
</TransPaymentInfo>
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
 
J

Joris Gillis

Hi,
I am looking to transform the above XML into the below structure
grouping payments with alike ones util there is a different payment
encountered. I also need to inculde a count of the like payments.

The following sample stylesheet produces the output you want.
<?xml version='1.0' encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput method="xml" indent="yes"/>


<xsl:template match="Amounts">
<Payments>
<xsl:apply-templates select="Amount[position()= 1 or . !=preceding::Amount[1]]"/>
</Payments>
</xsl:template>

<xsl:template match="Amount">
<xsl:variable name="count" select="count(following::Amount[. !=current()][1]/preceding::Amount) "/>
<xsl:variable name="cnt">
<xsl:if test="$count =0"><xsl:value-of select="count(../Amount)"/></xsl:if>
<xsl:if test="$count !=0"><xsl:value-of select="$count"/></xsl:if>
</xsl:variable>
<Payment amount="{.}" numpayments="{$cnt - count(preceding::Amount) }" />
</xsl:template>

</xsl:stylesheet>

regards,
 
M

Martin Honnen

Jody said:
I have already looked through those examples, but I did not find
anything that can answer my above question. Maybe I am not seeing it,
but there is no example there of what I am trying to accomplish.

To group you set up a key, then you can run through the elements, all
explained here
<http://www.jenitennison.com/xslt/grouping/muenchian.html>
To count nodes you use the count function of XPath:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:eek:utput method="xml" encoding="UTF-8" indent="yes" />

<xsl:key name="same-amount" match="Amount" use="." />

<xsl:template match="/">
<Payments>
<xsl:for-each select="Amounts/Amount[generate-id() =
generate-id(key('same-amount', .))]">
<Payment amount="{.}" numpayments="{count(key('same-amount', .))}" />
</xsl:for-each>
</Payments>
</xsl:template>

</xsl:stylesheet>
 
J

Jody Greening

This code (Joris's) works perfectly to organize and count elements in
the way that I explained above.

Thanks :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top