Ted,
In XSLT 2.0, this is much easier with a key:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="folder-by-ancestry" match="folder"
use="string-join(ancestor-or-self::*/@name,'#')"/>
<xsl:template match="folder">
<xsl:copy-of
select="key('folder-by-ancestry',string-join(ancestor-or-self::*/@name,'#'))"/>
</xsl:template>
</xsl:stylesheet>
(# is used as a delimiter on the assumption it's not allowed inside names.)
Unfortunately, XSLT/XPath 1.0 give no function that allows you to
stitch together all the names you need into a single key value.
Accordingly I'd probably use two passes to do this in 1.0: in the
first pass, annotate all the elements with a code (created by walking
through the tree and collecting @name attributes); in the second,
retrieve elements with the same code.
Pass 1:
<xsl:template match="folder">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:attribute name="ancestry">
<xsl:for-each select="ancestor-or-self::*/@name">
<xsl:value-of select="."/>
<xsl:text>#</xsl:text>
</xsl:for-each>
</xsl:attribute>
</xsl:copy>
</xsl:template>
Pass 2
<xsl:key name="folder-by-ancestry" match="folder" use="@ancestry"/>
<xsl:template match="folder">
<xsl:variable name="ancestry">
<xsl:for-each select="ancestor-or-self::*/@name">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="key('folder-by-ancestry',$ancestry)"/>
</xsl:template>
Cheers,
Wendell
I'd At 04:38 PM 9/26/2005, you wrote:
Thanks again to everyone who has replied to these messages. I had no
idea how hard this would be. It seemed so simple when I explained it
to the client ;-)
I'm looking for an XPath expression that will find all elements
whose ancestors are the same. By "same" I mean their @name is the
same at each level of ancestry (and they appear in the same order).
For example, this expression would return a count of 2 for the
following XML when filtered on the "daughter" folder (or "mother" or
"grandfather" for that matter).
<root>
<folder name="grandfather">
<folder name="mother">
<folder name="daughter" />
</folder>
</folder>
<folder name="grandfather">
<folder name="mother">
<folder name="daughter" />
</folder>
</folder>
<folder name="grandmother">
<folder name="father">
<folder name="son" />
</folder>
</folder>
</root>
I know it's going to be something like this, but I just can't get my
head around it!
<xsl:copy-of select="/root//folder[(_at_)name =
following-sibling::*/@name and ancestor-or-self::*/@name =
following-sibling::*/@name/ancestor-or-self::*/@name" />
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--