xsl-list
[Top] [All Lists]

RE: problem with multiple xsl:sort elements

2004-01-06 12:52:44
Sure, I can try to explain it.

Essentially it's a grouping problem (see 
http://www.jenitennison.com/xslt/grouping/muenchian.html). In your case you 
want to bring together all of the AccountLineItem nodes that have the same 
value for GLAccountNumber. Your summation is correct, we just grab each unique 
AccountLineItem/GLAccountNumber we encounter and the inner loop collects all 
the AccountLineItem nodes that match the GLAccountNumber. I may have never come 
up with this method on my own either, but that's why I read this list, it's a 
good place to learn new techniques. :)

Breaking down the selection:
select="AccountLineItem[GLAccountNumber[not(. = preceding::GLAccountNumber)]]

In English: 
Select all AccountLineItem nodes which have a child GLAccountNumber node that 
is not equal to any preceding GLAccountNumber nodes.

The preceding:: axis here would also grab GLAccountNumber nodes that are 
outside of AccountLIneItem nodes. In your case this doesn't matter, but to be 
more specific I probably should have written 
preceding::AccountLineItem/GLAccountNumber.

While writing this I noticed that you don't need to select the AccountLineItem 
nodes in the outer loop, but just the GLAccountNumber nodes. That would change 
the select statement to:

select="AccountLineItem/GLAccountNumber[not(. = 
preceding::AccountLineItem/GLAccountNumber)]"

In English:
select GLAccountNumber nodes that are children of AccountLineItem nodes, and 
are not equal to any preceding GLAccountNumber nodes that are children of 
AccountLineItem nodes.

The references to GLAccountNumber in the loop would change to self::node() or . 
(dot). Changing the select statement isn't critical, but it might make it 
easier to follow what is being used.

Enjoy,
Josh
-----Original Message-----
From: kakridge(_at_)bellsouth(_dot_)net 
[mailto:kakridge(_at_)bellsouth(_dot_)net]
Sent: Tuesday, January 06, 2004 6:21 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] problem with multiple xsl:sort elements


Josh, it seems like this code loops over the first node of every
different GLAccountNumber.  Then, it looks like an inner loop of all
nodes that match the node held in the outer loop.  Is this correct?  I
would have never thought of this.  I don't even really understand how it
works.

Can you explain this for me:

<xsl:for-each select="AccountLineItem[GLAccountNumber[not(. =
preceding::GLAccountNumber)]]">

Thanks.




-----Original Message-----
From: owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
[mailto:owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com] On Behalf Of 
Josh
Canfield
Sent: Monday, January 05, 2004 9:34 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] problem with multiple xsl:sort elements

Your problem is here:
<xsl:if test="not(GLAccountNumber = following::GLAccountNumber)">

following::GLAccountNumber is returning the next GLAccountNumber in
document order, not in the order that the for-each is iterating over the
elements.

One solution would be to group the AccountLineItem elements together by
GLAccountNumber and then output the subtotal after processing each
GLAccountNumber. 

<xsl:key name="account-by-number"
match="/ArrayOfAccountLineItem/AccountLineItem" use="GLAccountNumber"/>

<xsl:template match="ArrayOfAccountLineItem">

        <!-- iterate over distinct account numbers -->
        <xsl:for-each select="AccountLineItem[GLAccountNumber[not(. =
preceding::GLAccountNumber)]]">
                <xsl:sort select="GLAccountNumber" data-type="text"
order="ascending"/>
                <!-- iterate over all matching account numbers -->
                <xsl:for-each select="key('account-by-number',
GLAccountNumber)">
                        <xsl:sort select="substring(SettleDate,1,10)"
data-type="text" order="ascending"/>
                        <xsl:sort select="LineItemID" data-type="number"
order="ascending"/>

                        <xsl:apply-templates select="."/>

                </xsl:for-each>

                <!-- Summary line, used to be in xsl:if in the
AccountLineItem template-->
                <tr>
                        <td colspan="11">
                                &#xA0;
                        </td>
                </tr>
                <tr>
                        <td colspan="4">
                                &#xA0;
                        </td>
                        <td colspan="2" class="fieldName"
align="center">
                                Total by Object Code:
                        </td>
                        <td class="bottomFieldInfo" align="right">
<xsl:value-of select="format-number(sum(key('subTotal',
GLAccountNumber)/Amount[. &gt; 1]), '#.00')"/>
                        </td>
                        <td>
                                &#xA0;
                        </td>
                        <td class="bottomFieldInfo" align="right"
style="padding-right:5px">
<xsl:value-of select="translate(format-number(sum(key('subTotal',
GLAccountNumber)/Amount[. &lt; 0]), '#.00'), '-', '')"/>
                        </td>
                        <td colspan="2">
                                &#xA0;
                        </td>
                </tr>
                <tr>
                        <td colspan="11">
                                &#xA0;
                        </td>
                </tr>

                
        </xsl:for-each>
</table>
</xsl:template>

<xsl:template match="AccountLineItem">  
                        <tr>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="substring(LineItemName,1,35)"/>
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="position()"/>
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="GLAccountNumber"/>
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="substring(RegistrantFullName,1,19)"/>
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="concat(substring(SettleDate,6,2), '/',
substring(SettleDate,9,2), '/', substring(SettleDate,1,4))"/>
                                </td>                           
                                <td align="right" class="fieldInfo">
                                        <xsl:value-of
select="LineItemID"/>
                                </td>
                                <td class="fieldInfo" align="right">
                                        <xsl:choose>
                                                <xsl:when test="Amount
&gt; 0">
                                                        <xsl:value-of
select="format-number(Amount, '#.00')"/>
                                                </xsl:when>
                                                <xsl:otherwise>
                                                        &#xA0;
                                                </xsl:otherwise>
                                        </xsl:choose>
                                </td>
                                <td>
                                        &#xA0;
                                </td>
                                <td align="right" class="fieldInfo"
style="padding-right: 5px;">
                                        <xsl:choose>
                                                <xsl:when test="Amount
&lt; 0">
                                                        <xsl:value-of
select="translate(format-number(Amount, '#.00'), '-', '')"/>
                                                </xsl:when>
                                                <xsl:otherwise>
                                                        &#xA0;
                                                </xsl:otherwise>
                                        </xsl:choose>
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="substring(PaymentType,1,12)"/>                                  
                                </td>
                                <td class="fieldInfo">
                                        <xsl:value-of
select="substring(PaymentReference,1,15)"/>
                                </td>
                        </tr>
</xsl:template>


Hope this helps,
Josh

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list