Altova Mailing List Archives>Archive Index >microsoft.public.xsl Archive Home >Recent entries >Thread Prev - RE: Re-organize and sort source tree [Thread Next] RE: Re-organize and sort source treeTo: NULL Date: 10/11/2004 1:55:00 PM Hello Mukul:
I have a further question, if I may.
I would like to alter the xsl you have supplied so that I can further
"group" certain child elements. Following my previous posted xml sample, if
within a specific city I have multiple <office> elements and some of these
elements have the same value for the <name> child, then I want to copy just
the first occurrence of the <name> element, followed by all the <address>
siblings for that unique office name. So, the following fragment is a
modified version from the original xml I had posted:
<country name="China">
<offices>
<office id="BR6">
<names>
<name lang='en'>First Bank</name>
<name lang='ch'>第一家银行</name>
</names>
<address>
<line>China World Tower 2</line>
<line>2 Jian Guo Men Wai Avenue</line>
<line>Beijing</line>
</address>
<cities>
<city>Beijing</city>
</cities>
<phone>435345345</phone>
</office>
<office id="BR5">
<names>
<name lang='en'>First Bank</name>
<name lang='ch'>第一家银行</name>
</names>
<address>
<line>China World Tower 1</line>
<line>1 Jian Guo Men Wai Avenue</line>
<line>Beijing</line>
</address>
<cities>
<city>Beijing</city>
</cities>
<phone>888888888</phone>
</office>
</offices>
</country>
The office name is localized, so there can multiple versions of the same
value, each in a different language. Because of this, there are 4
significant differences:
1. The <name> element has been encapsulated by a new <names> parent
element, and
2. The <name> element has a new attribute - "lang" - to denote the relevant
language for the localized value.
3. All of the locations with the same office name are grouped under a new
<locations> parent element, with each location's relevant child elements
encapsulated by a <location> element.
4. The "id" attribute on the <office> element is no longer required in the
result tree.
I would like the transformed xml to maintain the ordering I originally
specified, but add the new grouping. The algorithm can assume that there
will always be an English version of the <name> element (e.g. lang='en') to
use for the grouping.
If possible, I would also like to extend the sort to the address/line
elements, so that all addresses for a particular office are sorted.
The result tree would look like the following:
<country name="China">
<cities>
<city>
<name>Beijing</name>
<offices>
<office>
<names>
<name lang='en'>First Bank</name>
<name lang='ch'>第一家银行</name>
</names>
<locations>
<location>
<address>
<line>China World Tower 1</line>
<line>1 Jian Guo Men Wai Avenue</line>
</address>
<phone>888888888</phone>
</location>
<location>
<address>
<line>China World Tower 2</line>
<line>2 Jian Guo Men Wai Avenue</line>
</address>
<phone>435345345</phone>
</location>
</locations>
</office>
</offices>
</city>
</cities>
</country>
Thank you again for any help you can offer!
"anyware" wrote:
> Mukul,
>
> I had managed to get that working myself (!). Thanks very much for your
> help; your solution works perfectly and is quite efficient. I appreciate
> your assistance.
>
> "Mukul Gandhi" wrote:
>
> > Please apply this correction -
> >
> > <xsl:for-each
> > select="msxsl:node-set($rtf)/temp/office/cities/city[generate-id(.) =
> > generate-id(key('by-city', .)[1])]">
> > <xsl:sort select="." />
> > <cities>
> > <city>
> > <name><xsl:value-of select="." /></name>
> >
> > <offices>
> > <xsl:for-each select="key('by-city', .)">
> > <xsl:sort select="../../name" />
> > <office id="{../../@id}">
> > <xsl:copy-of select="../preceding-sibling::name" />
> > <xsl:copy-of
> > select="../preceding-sibling::address" />
> > <xsl:copy-of select="../following-sibling::phone"
> > />
> > </office>
> > </xsl:for-each>
> > </offices>
> > </city>
> > </cities>
> > </xsl:for-each>
> >
> > I am applying Muenchian grouping to every offices node. For this reason, I
> > had to convert this variable <xsl:variable name="rtf"> (short for Result Tree
> > Fragment) into a node-set.
> >
> > To learn Muenchian grouping, please read here
> > http://www.jenitennison.com/xslt/grouping/index.html .
> >
> > Regards,
> > Mukul
> >
> > "anyware" wrote:
> >
> > > Hi Mukul:
> > >
> > > First, thanks very much for the reply and solution.
> > >
> > > It is almost perfect, just one flaw that I see. The <city> element is
> > > meant to encapsulate the <offices> element, but is instead appearing as its
> > > sibling. So, the xslt produces this fragment:
> > >
> > > <country name="Canada">
> > > <cities>
> > > <city>
> > > <name>Calgary</name>
> > > </city>
> > > <offices>
> > > <office id="Branch 2">
> > > <name>Canadian Branch</name>
> > > <address>
> > > <line>1 Prince Edward Boulevard</line>
> > > <line>5th Floor</line>
> > > <line>Room 10</line>
> > > <line>Calgary, Alberta</line>
> > > </address>
> > > <phone>(888) 888-8888</phone>
> > > </office>
> > > </offices>
> > > </cities>
> > >
> > > But what it should produce is:
> > >
> > > <country name="Canada">
> > > <cities>
> > > <city>
> > > <name>Calgary</name>
> > > <offices>
> > > <office id="Branch 2">
> > > <name>Canadian Branch</name>
> > > <address>
> > > <line>1 Prince Edward Boulevard</line>
> > > <line>5th Floor</line>
> > > <line>Room 10</line>
> > > <line>Calgary, Alberta</line>
> > > </address>
> > > <phone>(888) 888-8888</phone>
> > > </office>
> > > </offices>
> > > </city>
> > > </cities>
> > > </country>
> > >
> > > Also, I have seen similar usage of the Muenchian method that you are
> > > employing, but am having trouble understanding how it works. I can't figure
> > > out how the unique list of city keys is generated (i.e. how does
> > > generate-id() work?) and how the equality check
> > > (genrate-id(.)=generate-id(key)'by-city',.)) work? Would you mind explaining
> > > the following statement:
> > >
> > > <xsl:for-each
> > > select="msxsl:node-set($rtf)/temp/office/cities/city[generate-id(.) =
> > > generate-id(key('by-city', .)[1])]">
> > >
> > > Thanks again for all of your help!
> > >
> > >
> > >
> > > "Mukul Gandhi" wrote:
> > >
> > > > Please try this XSL -
> > > >
> > > > <?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">
> > > >
> > > > <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
> > > >
> > > > <xsl:key name="by-city" match="temp/office/cities/city" use="."/>
> > > >
> > > > <xsl:template match="/">
> > > > <locations>
> > > > <divisions>
> > > > <xsl:for-each select="locations/divisions/division">
> > > > <xsl:sort select="@id"/>
> > > > <division id="{@id}">
> > > > <regions>
> > > > <xsl:for-each select="regions/region">
> > > > <xsl:sort select="@name"/>
> > > > <region name="{@name}">
> > > > <countries>
> > > > <xsl:for-each select="countries/country">
> > > > <xsl:sort select="@name"/>
> > > > <country name="{@name}">
> > > > <xsl:variable name="rtf">
> > > > <temp>
> > > > <xsl:copy-of select="offices/office"/>
> > > > </temp>
> > > > </xsl:variable>
> > > > <xsl:for-each
> > > > select="msxsl:node-set($rtf)/temp/office/cities/city[generate-id(.) =
> > > > generate-id(key('by-city', .)[1])]">
> > > > <xsl:sort select="." />
> > > > <cities>
> > > > <city>
> > > > <name><xsl:value-of
> > > > select="." /></name>
> > > > </city>
> > > > <offices>
> > > > <xsl:for-each select="key('by-city', .)">
> > > > <xsl:sort select="../../name" />
> > > > <office id="{../../@id}">
> > > > <xsl:copy-of
> > > > select="../preceding-sibling::name" />
> > > > <xsl:copy-of
> > > > select="../preceding-sibling::address" />
> > > > <xsl:copy-of
> > > > select="../following-sibling::phone" />
> > > > </office>
> > > > </xsl:for-each> </offices>
> > > > </cities>
> > > > </xsl:for-each>
> > > > </country>
> > > > </xsl:for-each>
> > > > </countries>
> > > > </region>
> > > > </xsl:for-each>
> > > > </regions>
> > > > </division>
> > > > </xsl:for-each>
> > > > </divisions>
> > > > </locations>
> > > > </xsl:template>
> > > >
> > > > </xsl:stylesheet>
> > > >
> > > > Regards,
> > > > Mukul
> > > >
> > > > "anyware" wrote:
> > > >
> > > > > I'm struggling with using the Muenchian method to produce a result tree
> > > > > that re-organizes and sorts the
> > > > > source tree's nodes.
> > > > >
> > > > > The goal is to take the source tree and produce a result set that makes
> > > > > the
> > > > > child <cities> element (including its child <city> element) a parent of the
> > > > > <offices> element. The result tree would also be sorted by the following
> > > > > ascending order:
> > > > > division/@id, region/@name, country/@name, new cities/city/name location
> > > > > path, and office/name.
> > > > >
> > > > > I appreciate any assistance with the XSLT. Also, if possible, please
> > > > > include comments describing how the
> > > > > XSLT works. Thanks very much!
> > > > >
> > > > > Given the following source tree...
> > > > >
> > > > > <?xml version="1.0" encoding="UTF-8"?>
> > > > > <locations>
> > > > > <divisions>
> > > > > <division id="B">
> > > > > <regions>
> > > > > <region name="pacific">
> > > > > <countries>
> > > > > <country name="China">
> > > > > <offices>
> > > > > <office id="BR5">
> > > > > <name>Branch 5</name>
> > > > > <address>
> > > > > <line>China World Tower 1</line>
> > > > > <line>1 Jian Guo Men Wai Avenue</line>
> > > > > <line>Beijing</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>Beijing</city>
> > > > > </cities>
> > > > > <phone></phone>
> > > > > </office>
> > > > > </offices>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > </regions>
> > > > > </division>
> > > > > <division id="A">
> > > > > <regions>
> > > > > <region name="europe">
> > > > > <countries>
> > > > > <country name="Germany">
> > > > > <offices>
> > > > > <office id="BR3">
> > > > > <name>Branch 3</name>
> > > > > <address>
> > > > > <line>P.O. Box 1210</line>
> > > > > <line>Frankfurt, Germany</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>Frankfurt</city>
> > > > > </cities>
> > > > > <phone>+49-55-5555 5555</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </country>
> > > > > <country name="England">
> > > > > <offices>
> > > > > <office id="BR4">
> > > > > <name>Branch 4</name>
> > > > > <address>
> > > > > <line>26 Abbey Lane</line>
> > > > > <line>London</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>London</city>
> > > > > </cities>
> > > > > <phone>+44-22-2222 2222</phone>
> > > > > </office>
> > > > > <office id="BR5">
> > > > > <name>AAAAA Branch 4</name>
> > > > > <address>
> > > > > <line>7 Kings Highway</line>
> > > > > <line>London</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>London</city>
> > > > > </cities>
> > > > > <phone>+44-99-9999 9999</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > <region name="americas">
> > > > > <countries>
> > > > > <country name="United States">
> > > > > <offices>
> > > > > <office id="HO">
> > > > > <name>Home Office</name>
> > > > > <address>
> > > > > <line>P.O. Box 1234</line>
> > > > > <line>New York, NY 11111</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>New York</city>
> > > > > </cities>
> > > > > <phone>(212) 123-4567</phone>
> > > > > </office>
> > > > > <office id="BR1">
> > > > > <name>Branch 1</name>
> > > > > <address>
> > > > > <line>999 Main Street</line>
> > > > > <line>Suite 1200</line>
> > > > > <line>Miami, FL 22222</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>Miami</city>
> > > > > </cities>
> > > > > <phone>777-7777</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </country>
> > > > > <country name="Canada">
> > > > > <offices>
> > > > > <office id="Branch 2">
> > > > > <name>Canadian Branch</name>
> > > > > <address>
> > > > > <line>1 Prince Edward Boulevard</line>
> > > > > <line>5th Floor</line>
> > > > > <line>Room 10</line>
> > > > > <line>Calgary, Alberta</line>
> > > > > </address>
> > > > > <cities>
> > > > > <city>Calgary</city>
> > > > > </cities>
> > > > > <phone>(888) 888-8888</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > </regions>
> > > > > </division>
> > > > > </divisions>
> > > > > </locations>
> > > > >
> > > > >
> > > > > ...the XSLT would generate the following result tree:
> > > > >
> > > > > <?xml version="1.0" encoding="UTF-8"?>
> > > > > <locations>
> > > > > <divisions>
> > > > > <division id="A">
> > > > > <regions>
> > > > > <region name="americas">
> > > > > <countries>
> > > > > <country name="Canada">
> > > > > <cities>
> > > > > <city>
> > > > > <name>Calgary</name>
> > > > > <offices>
> > > > > <office id="Branch 2">
> > > > > <name>Canadian Branch</name>
> > > > > <address>
> > > > > <line>1 Prince Edward Boulevard</line>
> > > > > <line>5th Floor</line>
> > > > > <line>Room 10</line>
> > > > > <line>Calgary, Alberta</line>
> > > > > </address>
> > > > > <phone>(888) 888-8888</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > </cities>
> > > > > </country>
> > > > > <country name="United States">
> > > > > <cities>
> > > > > <city>
> > > > > <name>Miami</name>
> > > > > <offices>
> > > > > <office id="BR1">
> > > > > <name>Branch 1</name>
> > > > > <address>
> > > > > <line>999 Main Street</line>
> > > > > <line>Suite 1200</line>
> > > > > <line>Miami, FL 22222</line>
> > > > > </address>
> > > > > <phone>777-7777</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > <city>
> > > > > <name>New York</name>
> > > > > <offices>
> > > > > <office id="HO">
> > > > > <name>Home Office</name>
> > > > > <address>
> > > > > <line>P.O. Box 1234</line>
> > > > > <line>New York, NY 11111</line>
> > > > > </address>
> > > > > <phone>(212) 123-4567</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > </cities>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > <region name="europe">
> > > > > <countries>
> > > > > <country name="England">
> > > > > <cities>
> > > > > <city>
> > > > > <name>London</name>
> > > > > <offices>
> > > > > <office id="BR5">
> > > > > <name>AAAAA Branch 5</name>
> > > > > <address>
> > > > > <line>7 Kings Highway</line>
> > > > > <line>London</line>
> > > > > </address>
> > > > > <phone>+44-99-9999 9999</phone>
> > > > > </office>
> > > > > <office id="BR4">
> > > > > <name>Branch 4</name>
> > > > > <address>
> > > > > <line>26 Abbey Lane</line>
> > > > > <line>London</line>
> > > > > </address>
> > > > > <phone>+44-22-2222 2222</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > </cities>
> > > > > </country>
> > > > > <country name="Germany">
> > > > > <cities>
> > > > > <city>
> > > > > <name>Frankfurt</name>
> > > > > <offices>
> > > > > <office id="BR3">
> > > > > <name>Branch 3</name>
> > > > > <address>
> > > > > <line>P.O. Box 1210</line>
> > > > > <line>Frankfurt, Germany</line>
> > > > > </address>
> > > > > <phone>+49-55-5555 5555</phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > </cities>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > </regions>
> > > > > </division>
> > > > > <division id="B">
> > > > > <regions>
> > > > > <region name="pacific">
> > > > > <countries>
> > > > > <country name="China">
> > > > > <cities>
> > > > > <city>
> > > > > <name>Beijing</name>
> > > > > <offices>
> > > > > <office id="BR5">
> > > > > <name>Branch 5</name>
> > > > > <address>
> > > > > <line>China World Tower 1</line>
> > > > > <line>1 Jian Guo Men Wai Avenue</line>
> > > > > <line></line>
> > > > > </address>
> > > > > <phone></phone>
> > > > > </office>
> > > > > </offices>
> > > > > </city>
> > > > > </cities>
> > > > > </country>
> > > > > </countries>
> > > > > </region>
> > > > > </regions>
> > > > > </division>
> > > > > </divisions>
> > > > > </locations>
> > > > >
| ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
