Subject: RE: [xsl] Get XPath to Node from Node? From: Jeff Saylor <JSaylor@xxxxxxxxxxxxxxxxx> Date: Mon, 8 Jan 2001 12:19:37 -0500 |
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@xxxxxxxxx] Sent: Monday, January 08, 2001 11:37 AM To: JSaylor@xxxxxxxxxxxxxxxxx Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx 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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Get XPath to Node from No, Sachidanandam E.K | Thread | Re: [xsl] Get XPath to Node from No, David Carlisle |
RE: [xsl] xsl:key and document(), Robert Goheen | Date | Re: [xsl] xsl:key and document(), David Carlisle |
Month |