This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Retrieving Full XPATH expression
- To: <xsl-list at lists dot mulberrytech dot com>
- Subject: RE: [xsl] Retrieving Full XPATH expression
- From: "Tom Landon" <toml at hablador dot com>
- Date: Sat, 11 Aug 2001 08:21:53 -0700
- Reply-To: xsl-list at lists dot mulberrytech dot com
Ouch! Definitely a newbe mistake on my part. I knew about the string
comparison rule but obviously did not fully understand what I was writing.
Based on others' ideas I have since modified it to the following. The
source documents use a 'name' attribute extensively, so my solution is
customized to my particular project. It also outputs the attribute value,
again just for debugging purposes.
This does not look particularly efficient to me, but it is used only for
debugging purposed. Potential performance problems I see include:
1. Recursive implementation (versus for-each)
2. Template matching (versus call-template)
3. Count of the parent's elements (each iteration)
4. Count of the preceding-siblings (each iteration)
Are these as expensive as they look?
<!-- Root -->
<xsl:template match="/" mode="xpath">
<xsl:text>/</xsl:text>
</xsl:template>
<!-- Element -->
<xsl:template match="*" mode="xpath">
<!-- Process ancestors first -->
<xsl:apply-templates select=".." mode="xpath"/>
<!-- Output / if not already output by the root node -->
<xsl:if test="../..">/</xsl:if>
<!-- Output the name of the element -->
<xsl:value-of select="name()"/>
<!-- Add the element's position to pinpoint the element exactly -->
<xsl:if test="count(../*[name() = name(current())]) > 1">
<xsl:text>[</xsl:text>
<xsl:value-of
select="count(preceding-sibling::*[name() = name(current())]) +
1"/>
<xsl:text>]</xsl:text>
</xsl:if>
<!-- Add 'name' predicate as a hint of which element -->
<xsl:if test="@name">
<xsl:text/>[@name="<xsl:value-of select="@name"/>"]<xsl:text/>
</xsl:if>
</xsl:template>
<!-- Attribute -->
<xsl:template match="@*" mode="xpath">
<!-- Process ancestors first -->
<xsl:apply-templates select=".." mode="xpath"/>
<!-- Output the name of the attribute -->
<xsl:text/>/@<xsl:value-of select="name()"/>
<!-- Output the attribute's value as a predicate -->
<xsl:text/>[.="<xsl:value-of select="."/>"]<xsl:text/>
</xsl:template>
-----Original Message-----
From: owner-xsl-list@lists.mulberrytech.com
[mailto:owner-xsl-list@lists.mulberrytech.com]On Behalf Of Oleg
Tkachenko
Sent: Saturday, August 11, 2001 8:39 AM
To: xsl-list@lists.mulberrytech.com
Subject: RE: [xsl] Retrieving Full XPATH expression
Hello Tom !
> -----Original Message-----
> From: owner-xsl-list@lists.mulberrytech.com
> [mailto:owner-xsl-list@lists.mulberrytech.com]On Behalf Of Tom Landon
> Sent: Friday, August 10, 2001 8:51 PM
> To: xsl-list@lists.mulberrytech.com
> Subject: RE: [xsl] Retrieving Full XPATH expression
>
>
> This is not exactly what you need, but it might be a good starting point:
> <!-- Attribute node (test if node is in set of parent's
> attributes) -->
> <xsl:when test="$node = $node/../@*">
Do you realize that this conditional statement can surprisingly evaluate to
true for some element node either ?
An operator "=" applyed to nodes doesn't test one operand to be the same as
another one, it compares their string values instead.
For example, above test will be true for <Book> element:
<Books attr="value" >
<Book>value</Book>
</Books>
It's a little artificial example, but anyway I don't think it's a good way
to detect attribute node type, instead you can use one of thje following
approaches : count(. | ../@*) = count(../@*) or generate-id() =
generate-id(../@*[name()=name(current())]).
---
Oleg Tkachenko,
Multiconn International
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list