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

Re: Identity Transform Grouping Question

Subject: Re: Identity Transform Grouping Question
From: Anton Triest <anton@xxxxxxxx>
Date: Fri, 15 Oct 2004 09:30:45 +0200
my city triest
Hi Ethan,

Here's an updated version of the stylesheet I sent you in a previous thread (sep 29).

It does Muenchian grouping on the cities, just like in the previous version but with country information added to the key, to make sure cities with the same name in different countries are grouped correctly. I suppose that's why you used msxml:node-set()?

Then it groups the offices by their english name, and adds the location elements.


<?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:strip-space elements="*"/>

<!-- keys for grouping -->
<xsl:key name="cities" match="city" use="concat(ancestor::country/@name,'-',.)"/>
<xsl:key name="offices" match="office" use="concat(ancestor::country/@name,'-',names/name[@lang='en'])"/>


   <!-- identity transform: copy all elements -->
   <xsl:template match="*">
       <xsl:copy>
           <xsl:copy-of select="@*"/>
           <xsl:apply-templates/>
       </xsl:copy>
   </xsl:template>

   <!-- sort divisions by @id -->
   <xsl:template match="divisions">
       <divisions>
           <xsl:apply-templates select="division">
               <xsl:sort select="@id"/>
           </xsl:apply-templates>
       </divisions>
   </xsl:template>

   <!-- sort regions and countries by @name -->
   <xsl:template match="regions|countries">
       <xsl:copy>
           <xsl:apply-templates select="region|country">
               <xsl:sort select="@name"/>
           </xsl:apply-templates>
       </xsl:copy>
   </xsl:template>

<!-- reorganize 'country' elements -->
<xsl:template match="country">
<country>
<xsl:copy-of select="@*"/>
<cities>
<!-- group 'city' elements -->
<xsl:apply-templates select="offices/office/cities/city
[count(.|key('cities',concat(ancestor::country/@name,'-',.))[1])=1]">
<xsl:sort select="."/>
</xsl:apply-templates>
</cities>
</country>
</xsl:template>


<!-- new 'city' elements -->
<xsl:template match="city">
<city>
<name><xsl:value-of select="."/></name>
<offices>
<!-- group 'office' elements by their english name -->
<xsl:apply-templates select="ancestor::offices/office
[count(.|key('offices',concat(ancestor::country/@name,'-',names/name[@lang='en']))[1])=1]">
<xsl:sort select="names/name[@lang='en']"/>
</xsl:apply-templates>
</offices>
</city>
</xsl:template>


<!-- new office elements -->
<xsl:template match="office">
<office>
<xsl:apply-templates select="names"/>
<!-- add locations for each office with this name -->
<xsl:apply-templates select="key('offices',
concat(ancestor::country/@name,'-',names/name[@lang='en']))" mode="location"/>
</office>
</xsl:template>


<!-- new location elements -->
<xsl:template match="office" mode="location">
<location>
<xsl:copy-of select="@*"/><!-- this will copy @id from office to location -->
<xsl:apply-templates select="address|phone"/>
</location>
</xsl:template>


</xsl:stylesheet>


If you still have problems with this, let me know.
(I'm especially curious if there's any noticable performance loss as compared to your approach with node-set)


Best,
Anton



ethan.kalfus@xxxxxxx wrote:

<<Node trees don't contain markup, so don't have tags, and you can't have half a node, so you can never insert a closing tag anywhere, in particular you can't insert one at the location of this comment. The way to put a group of nodes as child elements of another node is to first create the wrapper node <foo> then inside that select all the elements that should go in the group </foo>

Perhaps my comments are misleading. My intent _is_ to explicitly wrap each unique group of <location> nodes -- that is, <location> nodes belonging to a unique <office> node -- with a surrounding <office></office> node (I said "tags" because my result tree is saved as an new xml file as input to another process -- so I am conceptualizing what that resulting xml file will look like, markup and all). My comments include complete markup (opening and closing tags) for this wrapper node; it is commented out because I could not successfully generate the wrapper node for each unique group, but wanted to show where the wrapper node should exist within the result tree. <<actually I'm not sure _why_ you are using msxsl:node-set() >>
Some of the XSLT, including this technique, was provided to me by another person on another site in order to assist me with using the Muenchian method for grouping <office> nodes within unique <city> nodes. A somewhat general explanation of my goal is that I want to sort the source tree according to several sort levels, then perform an identity transform that would reverse the parent-child relationship between the <city> and <office> nodes, and, finally, group <office> nodes according to their English name (office/names/name[@lang='en']), with each <office> node having one or more new <location> nodes to wrap the location-specific information, thus eliminating duplicate office/names nodes with the same name child. (I hope this is somewhat helpful!)
As I said, the current XSLT works wonderfully (transforming a 3MB file in 2 seconds) until the point of detail where I need to eliminate the duplicate office/names nodes. My XSLT seems to fail based on the mistaken idea that the use of preceding-sibling works with sorted nodes, which I now know it does not. So, the question is...once I have a sorted node set, what technique can I use to group those nodes according to a specific node value? Specifically, how do I ensure that the result tree contains office/names nodes with a unique name child (determined by the 'lang' attribute value = 'en')?

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.