 |
 |
 |
Hi,
I have an xslt that does most of what I need to do. It performs an
identity transform on the source tree, grouping and sorting elements as
appropriate (see NOTES below). I am having trouble getting the the nested
grouping correct. I am using the Muenchian method for the grouping and
for-each rather than templates -- I want to keep the for-each approach since
it seems to be close to working, just want to add the final piece to the
puzzle.
Some of the transform was provided to me by someone on this site and
performs well. It relies on the msxml extension function "node-set()", which
is acceptable. The xslt must be compatible with xslt 1.0 running under msxml
3.
The source tree looks like the following (NOTE: very simplified version of
actual
source -- please see NOTES below):
<office_locations>
<divisions>
<division id="A">
<regions>
<region name="europe">
<countries>
<country name="England">
<offices>
<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>
</regions>
</division>
</divisions>
</office_locations>
The result tree should look like this:
<office_locations>
<divisions>
<division id="A">
<regions>
<region name="europe">
<countries>
<country name="England">
<cities>
<city>
<name>London</name>
<offices>
<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>
<location>
<address>
<line>division A</line>
<line>44 Surrey Street</line>
<line>London</line>
</address>
<phone>+44-55-555 5555</phone>
</location>
</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>
<location id="BR7a">
<address>
<line>division A</line>
<line>22 Abbey Lane</line>
<line>London</line>
</address>
<phone>+44-55-555 5555</phone>
</location>
<location id="BR5a">
<address>
<line>division A</line>
<line>7 Kings Highway</line>
<line>London</line>
</address>
<phone>+44-99-9999 9999</phone>
</location>
</office>
</offices>
</city>
</cities>
</country>
</countries>
</region>
</regions>
</division>
</divisions>
</office_locations>
My current xslt looks like this:
<?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[@lang='en']" use="."/>
<xsl:template match="/">
<locations>
<divisions>
<xsl:for-each select="office_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[@lang='en' and
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="../../names/name[@lang='en']" />
<xsl:sort select="../preceding-sibling::address" />
<office
id="{../../@id}">
<xsl:copy-of
select="../preceding-sibling::names" />
<xsl:copy-of
select="../preceding-sibling::address" />
<xsl:copy-of
select="../following-sibling::phone" />
</office>
</xsl:for-each>
</offices>
</city>
</cities>
</xsl:for-each>
</country>
</xsl:for-each>
</countries>
</region>
</xsl:for-each>
</regions>
</division>
</xsl:for-each>
</divisions>
</locations>
</xsl:template>
</xsl:stylesheet>
NOTES:
1. The result tree only needs the English translation of <city> (e.g.
city[@lang='en']), but needs all translations of <office>.
2. Since an office with the same name can appear in more than one city in
more than one country in more than one region in more than one division,
nodes need to be grouped to account for this. Currently, the xslt groups
offices by city (according to the English translation, e.g. @lang='en'); the
missing piece is additionally grouping same-named offices (e.g.
names/name[@lang='en']) under their associated <city> parent node. What I
would like is to wrap each <office> node with a new parent -- "location". If
there is more than one office with the same name in the same city (and in the
same division/region/country), then only one <office> node should be created
(and with just one instance of its corresponding <names> child node), with
separate child <location> nodes beneath it for each office of the same name.
3. The result tree needs to be sorted in the following order (from least
granular to most granular): division/@id, region/@name, country/@name,
city[@lang='en'], office/names/name[@lang='en'], address.
Thanks for any help!
|
 | 

|  |
These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.
|  |
| |
 |
 |
 |