Connecting Tech Pros Worldwide Forums | Help | Site Map

Transforming with XSLT, Grouping elements until difference found.

Jody Greening
Guest
 
Posts: n/a
#1: Jul 20 '05
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


Martin Honnen
Guest
 
Posts: n/a
#2: Jul 20 '05

re: Transforming with XSLT, Grouping elements until difference found.




Jody Greening wrote:
[color=blue]
> 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[/color]

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

--

Martin Honnen
http://JavaScript.FAQTs.com/
Jody Greening
Guest
 
Posts: n/a
#3: Jul 20 '05

re: Transforming with XSLT, Grouping elements until difference found.


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:otherwise>
<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:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>

Joris Gillis
Guest
 
Posts: n/a
#4: Jul 20 '05

re: Transforming with XSLT, Grouping elements until difference found.


Hi,
[color=blue]
> 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.
>[/color]

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:output 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,
--
Joris Gillis (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)
Ceterum censeo XML omnibus esse utendum
Martin Honnen
Guest
 
Posts: n/a
#5: Jul 20 '05

re: Transforming with XSLT, Grouping elements until difference found.




Jody Greening wrote:
[color=blue]
> 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.[/color]

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:output 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>

--

Martin Honnen
http://JavaScript.FAQTs.com/
Jody Greening
Guest
 
Posts: n/a
#6: Jul 20 '05

re: Transforming with XSLT, Grouping elements until difference found.


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

Thanks :-)

Closed Thread