This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Get XPath to Node from Node?
- To: xsl-list at lists dot mulberrytech dot com
- Subject: RE: [xsl] Get XPath to Node from Node?
- From: Jeff Saylor <JSaylor at wizardfinance dot com>
- Date: Mon, 8 Jan 2001 12:19:37 -0500
- Reply-To: xsl-list at lists dot mulberrytech dot com
Dimitre,
That is an excellent piece of code - but it doesn't get me quite what I
need. Unfortunately, it generates a path with indexes to elements:
/root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']
Unfortunately, this won't work in my application because the source document
could have elements inserted which would throw off the indexed references.
I'm fortunate in that I will be dealing with elements that have (within the
scope of their peers) unique attributes, like:
<people>
<person name='jeff'>
<person name='jim'>
<person name='joe'>
</people>
If a user were to select person #2, I would need to be able to get
/people/person[@name='jim']
note that it's an absolute reference, not a relative one.
I will be looking at your code in some more detail to see if I can get it to
do what I need - I'm hoping to get it to sniff out the attributes of each
node up the tree and use those to build the XPath.
Any more ideas?
Cheers,
Jeff
-----Original Message-----
From: Dimitre Novatchev [mailto:dnovatchev@yahoo.com]
Sent: Monday, January 08, 2001 11:37 AM
To: JSaylor@wizardfinance.com
Cc: xsl-list@lists.mulberrytech.com
Subject: Re: [xsl] Get XPath to Node from Node?
Jeff Saylor wrote:
> I need to be able to get the node's XPath. Does anyone have an
> example for how to do this? I am using MSXML 3.0.
Hi Jeff,
Below is a sample xml document and a stylesheet that takes a node-set
parameter and produces one valid XPath expression for every
member-node.
stylesheet (buildPath.xsl):
-------------------------
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
>
<xsl:output method="text"/>
<xsl:variable name="theParmNodes" select="//namespace::*[local-name() =
'myNamespace']"/>
<xsl:template match="/">
<xsl:variable name="theResult">
<xsl:for-each select="$theParmNodes">
<xsl:variable name="theNode" select="."/>
<xsl:for-each select="$theNode |
$theNode/ancestor-or-self::node()[..]">
<xsl:element name="slash">/</xsl:element>
<xsl:choose>
<xsl:when test="self::*">
<xsl:element name="nodeName">
<xsl:value-of select="name()"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::*[name(current()) =
name()])"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::*[name(current()) =
name()])"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:otherwise> <!-- This node is not an element -->
<xsl:choose>
<xsl:when test="count(. | ../@*) = count(../@*)">
<!-- Attribute -->
<xsl:element name="nodeName">
<xsl:value-of select="concat('@',name())"/>
</xsl:element>
</xsl:when>
<xsl:when test="self::text()"> <!-- Text -->
<xsl:element name="nodeName">
<xsl:value-of select="'text()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::text())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::text())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<!-- Processing Instruction -->
<xsl:element name="nodeName">
<xsl:value-of select="'processing-instruction()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::processing-instruction())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::processing-instruction())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::comment()"> <!-- Comment -->
<xsl:element name="nodeName">
<xsl:value-of select="'comment()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::comment())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::comment())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<!-- Namespace: -->
<xsl:when test="count(. | ../namespace::*) =
count(../namespace::*)">
<xsl:variable name="apos">'</xsl:variable>
<xsl:element name="nodeName">
<xsl:value-of select="concat('namespace::*',
'[local-name() = ', $apos, local-name(), $apos, ']')"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="msxsl:node-set($theResult)"/>
</xsl:template>
</xsl:stylesheet>
xml source (buildPath.xml):
-------------------------
<!-- top level Comment -->
<root>
<nodeA>textA</nodeA>
<nodeA id="nodeA-2">
<?myProc ?>
xxxxxxxx
<nodeB/>
<nodeB xmlns:myNamespace="myTestNamespace">
<!-- Comment within /root/nodeA[2]/nodeB[2] -->
<nodeC/>
<!-- 2nd Comment within /root/nodeA[2]/nodeB[2] -->
</nodeB>
yyyyyyy
<nodeB/>
<?myProc2 ?>
</nodeA>
</root>
<!-- top level Comment -->
Result:
-------
/root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']
/root/nodeA[2]/nodeB[2]/nodeC/namespace::*[local-name() =
'myNamespace']
Hope this helps,
Dimitre Novatchev.
__________________________________________________
Do You Yahoo!?
Yahoo! Photos - Share your holiday photos online!
http://photos.yahoo.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list