[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Conditional Grouping Problem

Subject: Re: Conditional Grouping Problem
From: Ramkumar Menon <ram.menon@xxxxxxxxxx>
Date: Wed, 26 May 2004 13:55:23 +0530
xsl for each conditional
I had an alternative solution. But I relied on XSLT 2.0 [SAXON].

-Menon

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="products">
<xsl:variable name="current" select="."/>
<xsl:text>&#x0A;</xsl:text>
<xsl:comment>single product buyers by product name</xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:for-each-group select="product" group-by="name">
<name>
<xsl:value-of select="name"/>
</name>
<xsl:variable name="parentGroupName" select="name"/>
<xsl:for-each-group select="$current/product" group-by="buyer">
<xsl:if test="name = $parentGroupName and count($current/product[buyer=current-group()/buyer]) &lt; 2">
<buyer>
<xsl:value-of select="buyer"/>
</buyer>
</xsl:if>
</xsl:for-each-group>
</xsl:for-each-group>
<xsl:text>&#x0A;</xsl:text> <xsl:comment>multiple product buyers by buyer</xsl:comment>
<xsl:text>&#x0A;</xsl:text>
<xsl:for-each-group select="product" group-by="buyer">
<xsl:if test="count($current/product[buyer=current-group()/buyer]) &gt; 1">
<buyer>
<xsl:value-of select="buyer"/>
</buyer>
<xsl:variable name="parentGroupBuyer" select="buyer"/>
<xsl:for-each-group select="$current/product" group-by="name">
<xsl:if test="buyer=$parentGroupBuyer">
<name>
<xsl:value-of select="name"/>
</name>
</xsl:if>
</xsl:for-each-group>
</xsl:if>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>



James A. Robinson wrote:


If we focus on section 1 for now, I'm using the Muenchian Method with a
key like:
<xsl:key name="product-by-name" match="Product" use="name" />
How can I modify this key to match only products which are part of a single order (the Product's buyer only bought 1 item)?
I'm stretching my xsl knowledge here..



If we make the important assumption that each product element has a unique buyer/name pairing (in other words, Jane Doe & Our Worst Widget will only appear once), I believe you can use keys of buyers for products and products for buyers to achieve what you want (there may well be better ways of doing this, but I've had a few beers so please forgive any inefficiencies).

<?xml version="1.0" encoding="UTF-8" ?>
<!--
List all buyers of a single product by product
List all buyers of multiple products by buyer
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" indent="yes"/>

 <!-- all products keyed off of name -->
 <xsl:key name="products" match="product" use="string(name)"/>

 <!-- all buyers keyed off product name -->
 <xsl:key name="buyer_for_product" match="buyer" use="string(following-sibling::name)"/>

 <!-- all products keyed off of buyer -->
 <xsl:key name="products_for_buyer" match="product" use="string(buyer)"/>

 <!-- all buyers keyed of buyer name -->
 <xsl:key name="buyers" match="buyer" use="string(.)"/>

<xsl:template match="/">
<xsl:text>&#10;</xsl:text>
<xsl:comment>single product buyers by product name</xsl:comment>
<!-- for each unique product in list of purchased products -->
<xsl:for-each select="//product[generate-id() = generate-id(key('products', string(name))[1])]">
<!-- output product name -->
<name>
<xsl:value-of select="name"/>
</name>
<!-- for each buyer for this particular product -->
<xsl:for-each select="key('buyer_for_product', string(name))">
<!--
output buyer name if buyer purchased 1 product (i.e., only bought this one)
(it's important to note this assume UNIQUE product buyer & name pairings)
-->
<xsl:if test="count(key('products_for_buyer', string(.))) = 1">
<buyer>
<xsl:value-of select="."/>
</buyer>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
<xsl:text>&#10;</xsl:text>


   <xsl:comment>multiple product buyers by buyer</xsl:comment>
   <!-- for each unique buyer -->
   <xsl:for-each select="//buyer[generate-id() = generate-id(key('buyers', string(.))[1])]">
     <!--
       print buyer if they purhcased more than one product
       (it's important to note this assumes UNIQUE product buyer & name pairings)
     -->
     <xsl:if test="count(key('products_for_buyer', string(.))) &gt; 1">
       <buyer>
         <xsl:value-of select="."/>
       </buyer>
       <xsl:for-each select="key('products_for_buyer', string(.))">
         <product>
           <xsl:value-of select="string(name)"/>
         </product>
       </xsl:for-each>
     </xsl:if>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Results in:

<?xml version="1.0" encoding="utf-8"?>
<!--single product buyers by product name-->
<name>Our Best Widget</name>
<buyer>John Dow</buyer>
<buyer>Jane Doe</buyer>
<name>Our Worst Widget</name>
<buyer>Jill Doe</buyer>
<!--multiple product buyers by buyer-->
<buyer>John Q. Public</buyer>
<product>Our Best Widget</product>
<product>Our Worst Widget</product>

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.