[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
|
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>
</xsl:text>
<xsl:comment>single product buyers by product name</xsl:comment>
<xsl:text>
</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]) < 2">
<buyer>
<xsl:value-of select="buyer"/>
</buyer>
</xsl:if>
</xsl:for-each-group>
</xsl:for-each-group>
<xsl:text>
</xsl:text>
<xsl:comment>multiple product buyers by buyer</xsl:comment>
<xsl:text>
</xsl:text>
<xsl:for-each-group select="product" group-by="buyer">
<xsl:if
test="count($current/product[buyer=current-group()/buyer]) > 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> </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> </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(.))) > 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>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format
RSS 2.0 |
|
Atom 0.3 |
|
|