Subject: Re: [xsl] XSL/XPath 2.0 - most efficient way to find route to target element From: Robert Koberg <rob@xxxxxxxxxx> Date: Sun, 27 Apr 2008 09:02:51 -0400 |
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"/>o;? <node name="bat" id="b4"/> </node> <node>o;? <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[@name] except $bn/ancestor::node)/'../'"/> > <xsl:value-of separator="/" select="($bn/ancestor-or-self::node[@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. > ________________________________________________________________________
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSL/XPath 2.0 - most effi, David Carlisle | Thread | Re: [xsl] XSL/XPath 2.0 - most effi, Robert Koberg |
Re: [xsl] complicated xslt question, Florent Georges | Date | Re: [xsl] XSL/XPath 2.0 - most effi, Robert Koberg |
Month |