XML Editor
Sign up for a WebBoard account Sign Up Keyword Search Search More Options... Options
Chat Rooms Chat Help Help News News Log in to WebBoard Log in Not Logged in
Conferences Close Tree View
+ Stylus Studio Feature Requests (1192)
+ Stylus Studio Technical Forum (14621)
+ Website Feedback (249)
- XSLT Help and Discussion (7625)
-> - How do I substitute element ty... (1)
-> + How does one add working days ... (4)
-> - Help, I have existing XLT and... (1)
-> + Need help on XSLT issue - (2)
-> + EDI to XML Conversion (7)
-> - XML To JSON Conversion using X... (1)
-> + Formatting Paragraphs to same ... (2)
-> - Grouping of records (1)
-> + Problems with xsd 1.1 (4)
-> + XML to HL7 mapping (3)
-> + XSLT 3 and Iterate (2)
-> + XSL-FO to PDF preview (3)
-> + java.lang.RuntimeException: Er... (2)
-> + Create Acroforms with Stylus X... (2)
-- [1-20] [21-40] [41-60] Next
+ XQuery Help and Discussion (2016)
+ Stylus Studio FAQs (159)
+ Stylus Studio Code Samples & Utilities (364)
+ Stylus Studio Announcements (113)
Topic  
Postnext
Steven MatthewsSubject: keeping track of data
Author: Steven Matthews
Date: 01 May 2006 04:40 AM
Hi There,

I am using XSLT to format an XML file called orders.xml
I need to collect together the 'invoices_rec' elements for each customer with the same invoiceNum. I am using a loop but I need to find a way to
save the last invoice number in order to see if it has changed, so that I can compare it with the new invoiceNum.

I am using this variable:
<xsl:variable name="last_invoice_number" select="invoices/invoices_rec/invoiceNum"/>

I am using this test but it does not work:
<!-- Check that invoiceNum has changed -->
<xsl:if test="invoiceNum != $last_invoice_number">
code here
</xsl:if>

HERE IS THE FULL SOURCE CODE:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/database">
<html>
<body>
<h2>All Customer Invoices</h2>
<title>All Customer Invoices</title>

<!-- display FIRST customer details -->
<p />Ship to:<br/><br/>
<p /><xsl:value-of select="invoices/invoices_rec/contactName"/><br />
<xsl:value-of select="invoices/invoices_rec/shipToAddress"/><br />
<xsl:value-of select="invoices/invoices_rec/shipToCity"/><br />
<xsl:value-of select="invoices/invoices_rec/shipToState"/><br />
<xsl:value-of select="invoices/invoices_rec/shipToZip"/><br />

<!-- display FIRST customer invoice details -->
<br/><p />INVOICE NUMBER: <xsl:value-of select="invoices/invoices_rec/invoiceNum"/>
<p />SALES DATE: <xsl:value-of select="invoices/invoices_rec/salesDate"/><br/><br/>

<!-- Capture and store FIRST invoiceNum -->
<xsl:variable name="last_invoice_number" select="invoices/invoices_rec/invoiceNum"/>

<!-- display table headers -->
<table border="1">
<tr bgcolor="#9acd32">
<th>Product ID</th>
<th>Product Name</th>
<th>Product Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Extended Price</th>
</tr>

<!-- Start main loop here -->
<xsl:for-each select="invoices/invoices_rec">

<!-- Check that customer has changed -->
<xsl:if test="invoiceNum != $last_invoice_number">

<!-- display NEW customer details, since new customer -->
<p />Ship to:<br/><br/>
<p /><xsl:value-of select="contactName"/><br />
<xsl:value-of select="shipToAddress"/><br />
<xsl:value-of select="shipToCity"/><br />
<xsl:value-of select="shipToState"/><br />
<xsl:value-of select="shipToZip"/><br />

<!-- display NEW customer invoice details -->
<br/><p />INVOICE NUMBER: <xsl:value-of select="invoiceNum"/>
<p />SALES DATE: <xsl:value-of select="salesDate"/><br/><br/>

<!-- display new table headers -->
<table border="1">
<tr bgcolor="#9acd32">
<th>Product ID</th>
<th>Product Name</th>
<th>Product Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Extended Price</th>
</tr>
</table>

<!-- Store last invoiceNum -->
<xsl:for-each select="invoiceNum">
<xsl:variable name="last_invoice_number" select="."/>
</xsl:for-each>

</xsl:if>

<!-- display PRODUCT details in a table -->
<tr>
<td><xsl:value-of select="ProductID"/></td>
<td><xsl:value-of select="ProductName"/></td>
<td><xsl:value-of select="ProductDescription"/></td>
<td><xsl:value-of select="Quantity"/></td>
<td><xsl:value-of select="UnitPrice"/></td>
<td><xsl:value-of select="ExtendedPrice"/></td>
</tr>

</xsl:for-each>

<!-- Close last table -->
</table><br/><br/>

</body>
</html>

</xsl:template>
</xsl:stylesheet>

Any help would be appreciated,

regards,

Steven Matthews


Documentorders.xml
XML

Postnext
Ivan PedruzziSubject: keeping track of data
Author: Ivan Pedruzzi
Date: 01 May 2006 10:04 AM
Hi Steven,

This is a basic grouping problem, please use the attached solution to guide you in the right direction.

Hope this helps
Ivan Pedruzzi
Stylus Studio Team


Documentorders(1).xsl

Postnext
Steven MatthewsSubject: keeping track of data
Author: Steven Matthews
Date: 01 May 2006 02:22 PM
Thanks Ivan,

That really does work ! I spent two hours trying to figure out how to fix it and eventually gave up !

I am a newbie to XSL (as you can tell !), coming from a C/C++ background. It would seem that the logic with XSL is quite different from that in traditional programming languages. I have been trying to use that same programming logic with XSL !

One question, what does this condition actually mean:

<xsl:for-each select="invoices/invoices_rec[ generate-id(.) = generate-id( key('invoiceid', invoiceNum)[1])]"> ??

I really would like to know what is going on here ..

Thanks again for all the help

Steven Matthews, UK

Posttop
Ivan PedruzziSubject: keeping track of data
Author: Ivan Pedruzzi
Date: 01 May 2006 02:54 PM

That's grouping technique called Muenchian

1) I defined a key (it works like a hashmap in C++), so i can look-up an invoices_rec by invoiceNum

<xsl:key name="invoiceid" match="/database/invoices/invoices_rec" use="invoiceNum"/>

2) I iterate on each invoices_rec but only considreing the first one in the group (group by invoiceNum)

xsl:for-each select="invoices/invoices_rec[ generate-id(.) = generate-id( key('invoiceid', invoiceNum)[1])]">

invoices/invoices_rec[ ]
The expression inside the square brackets gets evaluated for each invoices_rec

key('invoiceid', invoiceNum)[1]
This returns a list of invoices_rec given invoiceNum in the context,
I take the first one.

generate-id
Returns a unique id for a given node that be used to check if two expressions are selecting the same node.


Here you can find several other technique
http://www.dpawson.co.uk/xsl/sect2/N4486.html

Hope this helps
Ivan Pedruzzi
Stylus Studio Team

   
Download A Free Trial of Stylus Studio 6 XML Professional Edition Today! Powered by Stylus Studio, the world's leading XML IDE for XML, XSLT, XQuery, XML Schema, DTD, XPath, WSDL, XHTML, SQL/XML, and XML Mapping!  
go

Log In Options

Site Map | Privacy Policy | Terms of Use | Trademarks
Stylus Scoop XML Newsletter:
W3C Member
Stylus Studio® and DataDirect XQuery ™are from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2016 All Rights Reserved.