Title: RE: XPath for a node
Hi, Arvind.
 
As I said, I needed such functionality badly. The problem for getting an XPath expression for a given node is that many XPath expressions can evalutate to the same node:
 
"/*/*[1]/*[7]" may be the same node as "//hallo"
 
Therefore I went the plain minimalistic approach, as you showed in you first post, to get the location path for a single node only. Using that during the project, I found out that the implemented solution worked for element nodes only, and I also wanted to be able to address text nodes, with absolute and relative paths. So my improved implementation was able to handle text nodes as well as relative paths, as long as the context node is in the ancestor axis of the target node. This is the code i posted.
 
There are many improvements I can think of, but with these limitations I still consider the function as minimalistic. It would be easy to handle PIs and comments, but it is very difficult to handle random context nodes. I fully agree with you that it makes no sense to traverse the whole dom tree just for this one location path.
 
Hiran
-----Urspr�ngliche Nachricht-----
Von: Arvind Gudipati [mailto:[EMAIL PROTECTED]]
Gesendet: Dienstag, 27. November 2001 15:20
An: [EMAIL PROTECTED]
Betreff: RE: XPath for a node

I certainly think its makes more sense to provide such functionality (to extract the XPath expression for a node), even though be it a minimalistic (not complete) functionality.

Meanwhile i guess i'd have to consider extracting the XPath expression by traversing the nodes in DOM tree.

Arvind

-----Original Message-----
From: Software AG [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, November 27, 2001 6:45 AM
To: '[EMAIL PROTECTED]'
Subject: AW: XPath for a node


Hi, there.

I also needed such functionality badly, and ended up writing my own method.
As I would appreciate someone having a look at this and maybe distribution
with the Xalan XPath API.

Anyway, here is my code:
----------------------------------------8<-----------
    /**
     * Returns the position of the node within the list of the parent's
children.
     * @param node The node whose position shall be calculated.
     * @return Position of the node. The first node has position=1 so these
values can be used
     * directly with XPath expressions.
     */
    public static int getNodePosition(Node node) {
        Node parent = node.getParentNode();
        if(parent==null)
            return 1;
       
        NodeList nl = parent.getChildNodes();
        for(int i=0;i<nl.getLength();i++) {
            if(nl.item(i)==node)
                return i+1;
        }
        return -1;
    }
   
    /**
     * Returns the position of the node within the list of the parent's
children.
     * This method counts only the nodes of the specified type.
     * @param node The node whose position shall be calculated.
     * @return Position of the node. The first node has position=1 so these
values can be used
     * directly with XPath expressions.
     */
    public static int getNodePosition(Node node, short nodetype) {
        Node parent = node.getParentNode();
        if(parent==null)
            return 1;
       
        NodeList nl = parent.getChildNodes();
        int pos = nl.getLength()-1;
        while(nl.item(pos)!=node)
            pos--;
       
        int count=pos-1;
        while(count>=0) {
            if(nl.item(count).getNodeType()!=nodetype)
                pos--;
            count --;
        }
        return pos+1;   //index is 1-based
    }
   
    /**
     * Returns the position of the node within the list of the parent's
children.
     * This method counts only the nodes with the given node name.
     * @param node The node whose position shall be calculated.
     * @return Position of the node. The first node has position=1 so these
values can be used
     * directly with XPath expressions.
     */
    public static int getNodePosition(Node node, String nodeName) {
        Node parent = node.getParentNode();
        if(parent==null)
            return 1;
       
        NodeList nl = parent.getChildNodes();
        int pos = nl.getLength()-1;
        while(nl.item(pos)!=node)
            pos--;
       
        int count=pos-1;
        while(count>=0) {
            if(!nl.item(count).getNodeName().equals(nodeName))
                pos--;
            count --;
        }
        return pos+1;   //index is 1-based
    }
   
    public static String getLocationPath(Node node) {
        return getLocationPath(node, null);
    }
   
    public static String getLocationPath(Node node, Node context) {
        if(node==null)
            return null;
       
        String result;
       
        if(node==context)
            return ".";
       
        switch(node.getNodeType()) {
            case Node.DOCUMENT_NODE:
                result = "";
                break;
            case Node.ELEMENT_NODE:
                result = getLocationPath(node.getParentNode(), context) +
"/"+node.getNodeName()+"["+getNodePosition(node, node.getNodeName())+"]";
                break;
            case Node.TEXT_NODE:
                result = getLocationPath(node.getParentNode(), context) +
"/text()["+getNodePosition(node, org.w3c.dom.Node.TEXT_NODE)+"]";
                break;
            default:
                result = getLocationPath(node.getParentNode(), context) +
"/*["+getNodePosition(node)+"]";
        }
       
        return result;
    }
   
    ---------------------------------------->8-----------


> -----Urspr�ngliche Nachricht-----
> Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]
> Gesendet: Dienstag, 27. November 2001 01:47
> An: [EMAIL PROTECTED]
> Betreff: Re: XPath for a node
>
>
>
> >     Is there any support in Xerces API to get the XPath
> value for a node
> > in a XML document?
>
> There's been lots of discussion about providing an XPath
> generating utility
> function, but I don't think anyone has ever gotten around to
> contributing
> one. The basic logic I'd try would be something like the following
> (untested!) pseudocode:
>
>      buffer=""
>      while(thisnode.getNodeType()!=DOCUMENT_NODE)
>      {
>           count=0;
>           name=thisnode.getNodeName();
>           for(prevsib=thisnode.getPreviousSibling();
>               prevsib!=null;
>               prevsib=prevsib.getPreviousSibling())
>           {
>                if(name.equals(prevsib.getNodeName())
>                     ++count;
>           }
>           buffer="/"+name+"["+count+"]"+buffer;
>      }
>
> As sketched that only works for elements; it'd have to be
> refined to deal
> with starting from other kinds of nodes. This sketch isn't
> namespace-aware;
> that'd also have to be fixed. And of course it assumes the
> node is in the
> main document tree; if it's part of an orphaned subtree or a
> DocumentFragment tree, you'd have to decide how best to
> represent that.
>
> A few days's hacking ought to be all that's needed, though.
> Good project
> for someone who's reasonably familiar with the DOM and wants
> to become more
> familiar with XPath to tackle and contribute to Xalan...
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
CONFIDENTIALITY NOTICE:  E-mail may contain confidential information that is legally protected.  Do not read this e-mail if you are not the intended recipient. This e-mail transmission, and any documents, files or previous e-mail messages  attached to it may contain confidential information that is legally protected.  If you are not the intended recipient or a person responsible for delivering it to the intended recipient,  you are hereby notified that any disclosure, copying, distribution or use of any of the information contained in or attached to this transmission is STRICTLY PROHIBITED.  If you have received this transmission in error, please immediately notify us by reply e-mail, by forwarding this to [EMAIL PROTECTED] or by telephone at (877) PANACYA, and destroy the original transmission and its attachments without reading or saving in any manner.  Thank you.  For information about PANACYA Inc., please visit our website at http://www.panacya.com.

Reply via email to