Subject: Re: [xsl] Identity Transform Grouping Question From: <ethan.kalfus@xxxxxxx> Date: Fri, 5 Nov 2004 15:14:04 -0500 |
Hello All: Due to the vast time and energy spent by Anton Triest, a solution is at hand. I'm posting it here for those struggling with nested grouping levels. Thanks very much to Anton for all of his time and help! XSLT: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> <!-- xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl" --> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/> <!-- keys for grouping --> <xsl:key name="cities" match="cities" use="city[@lang='en']"/> <xsl:key name="offices" match="office" use="concat(cities/city[@lang='en'],'-',names/name[@lang='en'])"/> <xsl:template match="/"> <xsl:comment> with apply-templates </xsl:comment> <xsl:apply-templates/> </xsl:template> <!-- 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 within this country --> <xsl:variable name="offices-in-this-country"> <xsl:copy-of select="offices"/> <!-- this is a trick, to restrict all subsequent key usage to this country only --> </xsl:variable> <xsl:apply-templates select="msxsl:node-set($offices-in-this-country)/offices/office/cities[count( .|key('cities',city[@lang='en'])[1])=1]"> <xsl:sort select="city[@lang='en']"/> </xsl:apply-templates> </cities> </country> </xsl:template> <!-- new 'city' elements --> <xsl:template match="cities"> <city name="{city[@lang='en']}"> <!-- (uncomment this if you need multilingual city names in the output) <city> <xsl:apply-templates select="city" mode="name"/> --> <offices> <!-- group 'office' elements located in this city by their english name --> <xsl:variable name="this-city" select="city[@lang='en']"/> <xsl:variable name="offices-in-this-city" select="../../../offices/office[cities/city[@lang='en']=$this-city]"/> <xsl:apply-templates select="$offices-in-this-city [count(.|key('offices', concat(cities/city[@lang='en'],'-',names/name[@lang='en']))[1])=1]"> <xsl:sort select="names/name[@lang='en']"/> </xsl:apply-templates> </offices> </city> </xsl:template> <!-- new city name elements --> <xsl:template match="city" mode="name"> <name> <xsl:copy-of select="@*"/> <xsl:value-of select="."/> </name> </xsl:template> <!-- new office elements --> <xsl:template match="office"> <office> <xsl:apply-templates select="names/name"/> <!-- add locations for each office with this name --> <xsl:apply-templates select="key('offices', concat(cities/city[@lang='en'],'-',names/name[@lang='en']))" mode="location"> <xsl:sort select="address"/> </xsl:apply-templates> </office> </xsl:template> <!-- new location elements --> <xsl:template match="office" mode="location"> <location> <xsl:copy-of select="@*"/> <xsl:apply-templates select="address|phone"/> </location> </xsl:template> </xsl:stylesheet> Sample XML: <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="locations-3.xsl" ?> <locations version="1.0"> <divisions> <division id="B"> <regions> <region name="americas"> <countries> <country name="United States"> <offices> <office id="HOb"> <names> <name lang='en'>Home Office</name> <name lang='fr'>Home Office (French)</name> <name lang='de'>Home Office (German)</name> </names> <address> <line>division B</line> <line>P.O. Box 1234</line> <line>New York, NY 11111</line> </address> <cities> <city lang='en'>New York</city> <city lang='fr'>New York (French)</city> <city lang='de'>New York (German)</city> </cities> <phone>(212) 123-4567</phone> </office> <office id="BR1b"> <names> <name lang='en'>Branch 1</name> <name lang='fr'>Branch 1 (French)</name> <name lang='de'>Branch 1 (German)</name> </names> <address> <line>division B</line> <line>999 Main Street</line> <line>Suite 1200</line> <line>Miami, FL 22222</line> </address> <cities> <city lang='en'>Miami</city> <city lang='fr'>Miami (French)</city> <city lang='de'>Miami (German)</city> </cities> <phone>777-7777</phone> </office> </offices> </country> <country name="Canada"> <offices> <office id="Branch 2b"> <names> <name lang='en'>Canadian Branch</name> <name lang='fr'>Canadian Branch (French)</name> <name lang='de'>Canadian Branch (German)</name> </names> <address> <line>division B</line> <line>1 Prince Edward Boulevard</line> <line>5th Floor</line> <line>Room 10</line> <line>Calgary, Alberta</line> </address> <cities> <city lang='en'>Calgary</city> <city lang='fr'>Calgary (French)</city> <city lang='de'>Calgary (German)</city> </cities> <phone>(888) 888-8888</phone> </office> </offices> </country> </countries> </region> <region name="pacific"> <countries> <country name="China"> <offices> <office id="BR5b"> <names> <name lang='en'>Branch 5</name> <name lang='fr'>Branch 5 (French)</name> <name lang='de'>Branch 5 (German)</name> </names> <address> <line>division B</line> <line>China World Tower 1</line> <line>1 Jian Guo Men Wai Avenue</line> <line>Beijing</line> </address> <cities> <city lang='en'>Beijing</city> <city lang='fr'>Beijing (French)</city> <city lang='de'>Beijing (German)</city> </cities> <phone/> </office> </offices> </country> </countries> </region> </regions> </division> <division id="A"> <regions> <region name="europe"> <countries> <country name="Germany"> <offices> <office id="BR3a"> <names> <name lang='en'>Branch 3</name> <name lang='fr'>Branch 3 (French)</name> <name lang='de'>Branch 3 (German)</name> </names> <address> <line>division A</line> <line>P.O. Box 1210</line> <line>Frankfurt, Germany</line> </address> <cities> <city lang='en'>Frankfurt</city> <city lang='fr'>Frankfurt (French)</city> <city lang='de'>Frankfurt (German)</city> </cities> <phone>+49-55-5555 5555</phone> </office> </offices> </country> <country name="England"> <offices> <office id="BR6a"> <names> <name lang='en'>Branch 4</name> <name lang='fr'>Branch 4 (French)</name> <name lang='de'>Branch 4 (German)</name> </names> <address> <line>division A</line> <line>26 Abbey Lane</line> <line>New Castle</line> </address> <cities> <city lang='en'>New Castle</city> <city lang='fr'>New Castle (French)</city> <city lang='de'>New Castle (German)</city> </cities> <phone>+44-22-2222 2222</phone> </office> <office id="BR5a"> <names> <name lang='en'>Branch 4</name> <name lang='fr'>Branch 4 (French)</name> <name lang='de'>Branch 4 (German)</name> </names> <address> <line>division A</line> <line>7 Kings Highway</line> <line>London</line> </address> <cities> <city lang='en'>London</city> <city lang='fr'>London (French)</city> <city lang='de'>London (German)</city> </cities> <phone>+44-99-9999 9999</phone> </office> <office id="BR8a"> <names> <name lang='en'>AAAABranch 4</name> <name lang='fr'>AAAABranch 4 (French)</name> <name lang='de'>AAAABranch 4 (German)</name> </names> <address> <line>division A</line> <line>44 Surrey Street</line> <line>London</line> </address> <cities> <city lang='en'>London</city> <city lang='fr'>London (French)</city> <city lang='de'>London (German)</city> </cities> <phone>+44-55-555 5555</phone> </office> <office id="BR7a"> <names> <name lang='en'>Branch 4</name> <name lang='fr'>Branch 4 (French)</name> <name lang='de'>Branch 4 (German)</name> </names> <address> <line>division A</line> <line>22 Abbey Lane</line> <line>London</line> </address> <cities> <city lang='en'>London</city> <city lang='fr'>London (French)</city> <city lang='de'>London (German)</city> </cities> <phone>+44-55-555 5555</phone> </office> </offices> </country> </countries> </region> <region name="americas"> <countries> <country name="United States"> <offices> <office id="HOa"> <names> <name lang='en'>Home Office</name> <name lang='fr'>Home Office (French)</name> <name lang='de'>Home Office (German)</name> </names> <address> <line>division A</line> <line>P.O. Box 1234</line> <line>New York, NY 11111</line> </address> <cities> <city lang='en'>New York</city> <city lang='fr'>New York (French)</city> <city lang='de'>New York (German)</city> </cities> <phone>(212) 123-4567</phone> </office> <office id="BR1a"> <names> <name lang='en'>Branch 1</name> </names> <address> <line>division A</line> <line>999 Main Street</line> <line>Suite 1200</line> <line>Miami, FL 22222</line> </address> <cities> <city lang='en'>Miami</city> <city lang='fr'>Miami (French)</city> <city lang='de'>Miami (German)</city> </cities> <phone>777-7777</phone> </office> </offices> </country> <country name="Canada"> <offices> <office id="Branch 2a"> <names> <name lang='en'>Canadian Branch</name> <name lang='fr'>Canadian Branch (French)</name> <name lang='de'>Canadian Branch (German)</name> </names> <address> <line>division A</line> <line>1 Prince Edward Boulevard</line> <line>5th Floor</line> <line>Room 10</line> <line>Calgary, Alberta</line> </address> <cities> <city lang='en'>Calgary</city> <city lang='fr'>Calgary (French)</city> <city lang='de'>Calgary (German)</city> </cities> <phone>(888) 888-8888</phone> </office> </offices> </country> </countries> </region> </regions> </division> </divisions> </locations> Visit our website at http://www.ubs.com This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. E-mail transmission cannot be guaranteed to be secure or error-free as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. The sender therefore does not accept liability for any errors or omissions in the contents of this message which arise as a result of e-mail transmission. If verification is required please request a hard-copy version. This message is provided for informational purposes and should not be construed as a solicitation or offer to buy or sell any securities or related financial instruments.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Are there any tools that , Bill Riegel | Thread | Re: [xsl] Identity Transform Groupi, Geert Josten |
RE: [xsl] XSLT 1.0: Grouping Adjace, Joe Heidenreich | Date | RE: [xsl] Are there any tools that , Michael Kay |
Month |