Here is a slightly more reasonable verion of the XSL. I moved the common
path building to a common template and I am using last() to find the
closest common ancestor in the two sequences (they should be in document
order, right?). But it still doesn't work.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:key name="config" match="*" use="@id"/>
<xsl:template match="/">
<test>
<xsl:apply-templates select="key('config', 'a3')" mode="path">
<xsl:with-param name="target-id" select="'b3'"/>
</xsl:apply-templates>
<xsl:apply-templates select="key('config', 'b4')" mode="path">
<xsl:with-param name="target-id" select="'b3'"/>
</xsl:apply-templates>
<xsl:apply-templates select="key('config', 'c3')" mode="path">
<xsl:with-param name="target-id" select="'b3'"/>
</xsl:apply-templates>
</test>
</xsl:template>
<xsl:template match="*" mode="path">
<xsl:param name="target-id"/>
<xsl:variable name="target-anc-and-self">
<xsl:apply-templates select="key('config', $target-id)"
mode="ancestry"/>
</xsl:variable>
<xsl:variable name="anc-and-self">
<xsl:apply-templates select="." mode="ancestry"/>
</xsl:variable>
<xsl:variable name="common-ancestor" select="($anc-and-self
intersect $target-anc-and-self)[last()]"/>
<xsl:copy-of select="$common-ancestor"/>
<xsl:variable name="path-to-target">
<xsl:apply-templates select="." mode="path-up">
<xsl:with-param name="common-ancestor"
select="$common-ancestor"/>
</xsl:apply-templates>
<xsl:apply-templates select="key('config', $target-id)"
mode="path-down">
<xsl:with-param name="common-ancestor"
select="$common-ancestor"/>
</xsl:apply-templates>
</xsl:variable>
<path href="{$path-to-target}"/>
</xsl:template>
<xsl:template match="*" mode="ancestry">
<xsl:sequence select="ancestor-or-self::*"/>
</xsl:template>
<xsl:template match="*" mode="path-up">
<xsl:param name="common-ancestor"/>
<xsl:choose>
<xsl:when test=". = $common-ancestor"/>
<xsl:otherwise>
<xsl:text>../</xsl:text>
<xsl:apply-templates select="parent::*" mode="path-up"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="path-down">
<xsl:param name="common-ancestor"/>
<xsl:choose>
<xsl:when test=". = $common-ancestor"/>
<xsl:otherwise>
<xsl:apply-templates select="parent::*" mode="path-down"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
On Sun, 2008-04-27 at 09:02 -0400, Robert Koberg wrote:
Here is what I tried (probably uses too much XSLT 1.0 thinking), but it
does not work. I tried using intersect to get the nearest common
ancestor, but I can't seem to get it. What am I doing wrong?
The XSL is followed by the XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:key name="config" match="*" use="@id"/>
<xsl:template match="/">
<test>
<xsl:variable name="target" select="key('config', 'b3')"/>
<xsl:variable name="target-anc-and-self">
<xsl:apply-templates select="key('config', 'b3')"
mode="ancestry"/>
</xsl:variable>
<xsl:variable name="a3-anc-and-self">
<xsl:apply-templates select="key('config', 'a3')"
mode="ancestry"/>
</xsl:variable>
<xsl:variable name="a3-common-ancestor" select="($a3-anc-and-self
intersect $target-anc-and-self)[1]"/>
<xsl:copy-of select="$a3-common-ancestor"/>
<xsl:variable name="a3-to-target">
<xsl:apply-templates select="key('config', 'a3')"
mode="path-up">
<xsl:with-param name="common-ancestor"
select="$a3-common-ancestor"/>
</xsl:apply-templates>
<xsl:apply-templates select="$target" mode="path-down">
<xsl:with-param name="common-ancestor"
select="$a3-common-ancestor"/>
</xsl:apply-templates>
</xsl:variable>
<path href="{$a3-to-target}"/>
<xsl:variable name="b4-anc-and-self">
<xsl:apply-templates select="key('config', 'b4')"
mode="ancestry"/>
</xsl:variable>
<xsl:variable name="b4-common-ancestor" select="($b4-anc-and-self
intersect $target-anc-and-self)[1]"/>
<xsl:copy-of select="$b4-common-ancestor"/>
<xsl:variable name="b4-to-target">
<xsl:apply-templates select="key('config', 'b4')"
mode="path-up">
<xsl:with-param name="common-ancestor"
select="$b4-common-ancestor"/>
</xsl:apply-templates>
<xsl:apply-templates select="$target" mode="path-down">
<xsl:with-param name="common-ancestor"
select="$b4-common-ancestor"/>
</xsl:apply-templates>
</xsl:variable>
<path href="{$b4-to-target}"/>
<xsl:variable name="c3-anc-and-self">
<xsl:apply-templates select="key('config', 'c3')"
mode="ancestry"/>
</xsl:variable>
<xsl:variable name="c3-common-ancestor" select="($c3-anc-and-self
intersect $target-anc-and-self)[1]"/>
<xsl:copy-of select="$c3-common-ancestor"/>
<xsl:variable name="c3-to-target">
<xsl:apply-templates select="key('config', 'c3')"
mode="path-up">
<xsl:with-param name="common-ancestor"
select="$c3-common-ancestor"/>
</xsl:apply-templates>
<xsl:apply-templates select="$target" mode="path-down">
<xsl:with-param name="common-ancestor"
select="$c3-common-ancestor"/>
</xsl:apply-templates>
</xsl:variable>
<path href="{$c3-to-target}"/>
</test>
</xsl:template>
<xsl:template match="*" mode="ancestry">
<xsl:sequence select="ancestor-or-self::*"/>
</xsl:template>
<xsl:template match="*" mode="path-up">
<xsl:param name="common-ancestor"/>
<xsl:choose>
<xsl:when test=". = $common-ancestor"/>
<xsl:otherwise>
<xsl:text>../</xsl:text>
<xsl:apply-templates select="parent::*" mode="path-up"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="path-down">
<xsl:param name="common-ancestor"/>
<xsl:choose>
<xsl:when test=". = $common-ancestor"/>
<xsl:otherwise>
<xsl:apply-templates select="parent::*" mode="path-down"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<node name="foo" id="x">
<node name="bar" id="b1">
<node>
<node/>
<node/>
</node>
<node name="baz" id="b2">
<node name="bat" id="b3"/>
<node name="bat" id="b4"/>
</node>
<node>
<node name="saz" id="c2">
<node name="sat" id="c3"/>
</node>
</node>
</node>
<node name="gar" id="a1">
<node name="gaz" id="a2">
<node name="gat" id="a3"/>
<node/>
</node>
<node>
<node/>
</node>
<node>
<node/>
</node>
</node>
</node>
On Sat, 2008-04-26 at 23:43 +0100, David Carlisle wrote:
This doesn't get quite the result you ask for I get ../bat for the last
one, also I assume that nodes without a name should not contribute to
the path (otherwise I'd need an extra ../ to get out of the unnamed
node that contains c2).
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="data:,f">
<xsl:key name="id" match="*" use="@id"/>
<xsl:variable name="r" select="/"/>
<xsl:template match="/">
a3 to b3 <xsl:value-of select="f:path('a3','b3')"/>
c3 to b3 <xsl:value-of select="f:path('c3','b3')"/>
b4 to b3 <xsl:value-of select="f:path('b4','b3')"/>
</xsl:template>
<xsl:function name="f:path">
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:variable name="an" select="key('id',$a,$r)"/>
<xsl:variable name="bn" select="key('id',$b,$r)"/>
<xsl:value-of>
<xsl:sequence select="($an/ancestor-or-self::node[(_at_)name] except
$bn/ancestor::node)/'../'"/>
<xsl:value-of separator="/"
select="($bn/ancestor-or-self::node[(_at_)name] except
$an/ancestor::node)/@name"/>
</xsl:value-of>
</xsl:function>
</xsl:stylesheet>
________________________________________________________________________
The Numerical Algorithms Group Ltd is a company registered in England
and Wales with company number 1249803. The registered office is:
Wilkinson House, Jordan Hill Road, Oxford OX2 8DR, United Kingdom.
This e-mail has been scanned for all viruses by Star. The service is
powered by MessageLabs.
________________________________________________________________________
--~------------------------------------------------------------------
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>
--~--
--~------------------------------------------------------------------
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>
--~--
--~------------------------------------------------------------------
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>
--~--