.NETGURU
current xml path location
Messages   Related Types
This message was discovered on ASPFriends.com 'aspngxml' list.


Ahmed, Salman
While I am traversing through my XML, is it possible for me to get the PATH
of where I am at any given moment in the xml?

There doesn't seem to be this functionality...is this possible?

Reply to this message...
 
    
Kirk Allen Evans
[Original message clipped]

This should work, but will not include the current node if it is an
attribute.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:template match="goo">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:text />/
            <xsl:value-of select="name()" />
            <xsl:text />[
            <xsl:number />]
            <xsl:text />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

If you need something more significant, then see Dimitre Novatchev's example
on Dave Pawson's FAQ [1].

[1] http://www.dpawson.co.uk/xsl/sect2/N6077.html

Kirk Allen Evans
http://www.xmlandasp.net
"XML and ASP.NET", New Riders Publishing
http://www.amazon.com/exec/obidos/ASIN/073571200X

Reply to this message...
 
    
Ahmed, Salman
Actually what I meant was I am parsing the XML using the DOM, I need to know
where I am in the XML at any given time..is this possible?

-----Original Message-----
From: Kirk Allen Evans [mailto:Click here to reveal e-mail address]
Sent: Wednesday, July 31, 2002 11:00 AM
To: aspngxml
Subject: [aspngxml] RE: current xml path location

[Original message clipped]

This should work, but will not include the current node if it is an
attribute.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:template match="goo">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:text />/
            <xsl:value-of select="name()" />
            <xsl:text />[
            <xsl:number />]
            <xsl:text />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

If you need something more significant, then see Dimitre Novatchev's example
on Dave Pawson's FAQ [1].

[1] http://www.dpawson.co.uk/xsl/sect2/N6077.html

Kirk Allen Evans
http://www.xmlandasp.net
"XML and ASP.NET", New Riders Publishing
http://www.amazon.com/exec/obidos/ASIN/073571200X

| [aspngxml] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngxml.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives

Reply to this message...
 
    
Kirk Allen Evans
[Original message clipped]

You could use the stylesheet provided to write the information out for you
and then interrogate the resulting tree. However, if you must loop through
the DOM, you can still achieve it. There is nothing built-in to determine
the XPath to the current node, but you can write a recursive function to do
the same. The trick to it is finding the position() of the current node:
the DOM has no such concept at the node level, so you have to keep
requerying the preceding-sibling axis to determine what the relative
position of the node is at any given point. Note that this is a VERY
inefficient example, especially for very large documents where the
preceding-sibling axis can become quite large.

Private Sub Command1_Click()
Dim doc As MSXML2.DOMDocument40
Dim node As MSXML2.IXMLDOMNode

Set doc = New MSXML2.DOMDocument40
doc.async = False
doc.Load ("d:\temp\results.xml")

Set node = doc.selectSingleNode("dsPart/Part[2]/descr")

Debug.Print RecurseNodes(vbNullString, node)
set node = nothing
set doc = nothing
End Sub

Private Function RecurseNodes(ByRef strPath As String, ByRef CurrentNode As
MSXML2.IXMLDOMNode) As String
Dim lngPosition As Long

lngPosition = CurrentNode.selectNodes("preceding-sibling::*[name()='" &
CurrentNode.nodeName & "']").length + 1
strPath = "/" & CurrentNode.nodeName & "[" & lngPosition & "]" & strPath
If Not CurrentNode.parentNode Is Nothing Then
If CurrentNode.parentNode.nodeType <> NODE_DOCUMENT Then
RecurseNodes strPath, CurrentNode.parentNode
End If
End If
RecurseNodes = strPath
End Function

Kirk Allen Evans
http://www.xmlandasp.net
"XML and ASP.NET", New Riders Publishing
http://www.amazon.com/exec/obidos/ASIN/073571200X

Reply to this message...
 
    
Dan Wahlin
You'll have to write some code for this, but I came across the following
example that should help get you started. They want to accomplish
something different but end up creating an XPath expression along the
way to get to the desired end result (I haven't actually tried the code
out so you'll have to experiment):

http://groups.google.com/groups?q=DOM+XPATH+path+.NET&hl=en&lr=&ie=UTF-8
&oe=UTF-8&selm=c909239.0206171642.4b165c55%40posting.google.com&rnum=3

Dan Wahlin

Wahlin Consulting LLC
Microsoft MVP - ASP.NET
http://www.XMLforASP.Net: #1 ASP.NET XML Resource
XML for ASP.NET Developers by Dan Wahlin in bookstores everywhere!

-----Original Message-----
From: Ahmed, Salman [mailto:Click here to reveal e-mail address]
Sent: Wednesday, July 31, 2002 7:36 AM
To: aspngxml
Subject: [aspngxml] current xml path location

While I am traversing through my XML, is it possible for me to get the
PATH
of where I am at any given moment in the xml?

There doesn't seem to be this functionality...is this possible?

| [aspngxml] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngxml.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives

Reply to this message...
 
    
Kirk Allen Evans
Heh... yeah... the thread that Leigh mentions [1] in the post actually
started a lengthy back-and-forth with Microsoft about document ordering for
XPath (they determined it as designed, XPath document ordering is ambiguous
for reverse axes in the W3C rec). The original solution I posted on
microsoft.public.dotnet.xml [1] is flawed in that it does not account for
calculating the position of the node. This can be overcome with the
following:

        private string GetPathFromNode(XmlNode baseNode)
        {
            string path = "";
            XmlNodeList nodes = baseNode.SelectNodes("ancestor-or-self::*");
            foreach(XmlNode node in nodes)
            {
                int nodePosition = node.SelectNodes("preceding-sibling::*[name()='" +
node.Name + "']").Count +1;

                path += "/" + node.Name + "[" + nodePosition + "]";

            } return(path);
        }

However, this also falls apart if namespaces are used in the input document.
This is because of the line:

    preceding-sibling::*[name()='" + node.Name + "']

This gets all nodes having that name, whether they are in the same namespace
or not. So, the position predicate will give incorrect results. To
definitely support positional predicates, support the default namespace
concept, and still get the correct XPath back, you have to accomodate for
the namespaces. Note that the node.Prefix property will not be filled for
the current node if it is in the default namespace. That is why you see the

To overcome that, you can use the namespace-uri() XPath expression as well:

        private string GetQName(XmlNode node)
        {
            string qname = string.Empty;

            if (node.NamespaceURI.CompareTo(string.Empty) != 0)
            {
                if (node.Prefix.CompareTo(string.Empty) != 0)
                {
                    //If the prefix is present, use it.

                    if (node.NodeType == XmlNodeType.Attribute){qname = "@";}
                    qname = qname + node.Prefix + ":" + node.LocalName ;
                }
                else
                {
                    //The node is in the default namespace, the prefix is not
                    //present.
                    if (node.NodeType == XmlNodeType.Attribute)
                        qname = "@*[local-name() = '" + node.LocalName + "' and
namespace-uri()='" + node.NamespaceURI + "']";
                    else
                        qname = "node()[local-name() = '" + node.LocalName + "' and
namespace-uri()='" + node.NamespaceURI + "']";
                }
            }
            else
            {
                if (node.NodeType == XmlNodeType.Attribute)
                    qname = "@" + node.Name;
                else
                    qname = node.Name;
            }
            return(qname);
        }
        private string GetPathFromNode(XmlNode baseNode)
        {
            string path = "";
            XmlNodeList nodes = null;
            if(baseNode.NodeType == XmlNodeType.Attribute )
            {
                nodes = baseNode.SelectNodes("ancestor::*");
            }
            else
            {
                nodes = baseNode.SelectNodes("ancestor-or-self::* |
ancestor-or-self::@*");
            }
            foreach(XmlNode node in nodes)
            {
                int nodePosition =
node.SelectNodes("preceding-sibling::*[local-name()='" + node.LocalName + "'
and namespace-uri()='" + node.NamespaceURI + "']").Count +1;
                path += "/" + GetQName(node) + "[" + nodePosition.ToString() + "]";
            }
            if(baseNode.NodeType == XmlNodeType.Attribute)
                path += "/" + GetQName(baseNode);
            return(path);
        }

[1]
http://groups.google.com/groups?q=Getting+%22path%22+of+an+XmlNode++group:mi
crosoft.public.dotnet.xml&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=%232rIkVm4BHA.198
4%40tkmsftngp02&rnum=1

[Original message clipped]

Reply to this message...
 
    
Dan Wahlin
Good stuff Kirk. Thanks for posting it. :)

Dan

Wahlin Consulting LLC
Microsoft MVP - ASP.NET
http://www.XMLforASP.Net: #1 ASP.NET XML Resource
XML for ASP.NET Developers by Dan Wahlin in bookstores everywhere!

-----Original Message-----
From: Kirk Allen Evans [mailto:Click here to reveal e-mail address]
Sent: Wednesday, July 31, 2002 1:17 PM
To: aspngxml
Subject: [aspngxml] RE: current xml path location

Heh... yeah... the thread that Leigh mentions [1] in the post actually
started a lengthy back-and-forth with Microsoft about document ordering
for
XPath (they determined it as designed, XPath document ordering is
ambiguous
for reverse axes in the W3C rec). The original solution I posted on
microsoft.public.dotnet.xml [1] is flawed in that it does not account
for
calculating the position of the node. This can be overcome with the
following:

        private string GetPathFromNode(XmlNode baseNode)
        {
            string path = "";
            XmlNodeList nodes =
baseNode.SelectNodes("ancestor-or-self::*");
            foreach(XmlNode node in nodes)
            {
                int nodePosition =
node.SelectNodes("preceding-sibling::*[name()='" +
node.Name + "']").Count +1;

                path += "/" + node.Name + "[" +
nodePosition + "]";

            } return(path);
        }

However, this also falls apart if namespaces are used in the input
document.
This is because of the line:

    preceding-sibling::*[name()='" + node.Name + "']

This gets all nodes having that name, whether they are in the same
namespace
or not. So, the position predicate will give incorrect results. To
definitely support positional predicates, support the default namespace
concept, and still get the correct XPath back, you have to accomodate
for
the namespaces. Note that the node.Prefix property will not be filled
for
the current node if it is in the default namespace. That is why you see
the

To overcome that, you can use the namespace-uri() XPath expression as
well:

        private string GetQName(XmlNode node)
        {
            string qname = string.Empty;

            if (node.NamespaceURI.CompareTo(string.Empty) !=
0)
            {
                if (node.Prefix.CompareTo(string.Empty)
!= 0)
                {
                    //If the prefix is present, use
it.

                    if (node.NodeType ==
XmlNodeType.Attribute){qname = "@";}
                    qname = qname + node.Prefix +
":" + node.LocalName ;
                }
                else
                {
                    //The node is in the default
namespace, the prefix is not
                    //present.
                    if (node.NodeType ==
XmlNodeType.Attribute)
                        qname = "@*[local-name()
= '" + node.LocalName + "' and
namespace-uri()='" + node.NamespaceURI + "']";
                    else
                        qname =
"node()[local-name() = '" + node.LocalName + "' and
namespace-uri()='" + node.NamespaceURI + "']";
                }
            }
            else
            {
                if (node.NodeType ==
XmlNodeType.Attribute)
                    qname = "@" + node.Name;
                else
                    qname = node.Name;
            }
            return(qname);
        }
        private string GetPathFromNode(XmlNode baseNode)
        {
            string path = "";
            XmlNodeList nodes = null;
            if(baseNode.NodeType == XmlNodeType.Attribute )
            {
                nodes =
baseNode.SelectNodes("ancestor::*");
            }
            else
            {
                nodes =
baseNode.SelectNodes("ancestor-or-self::* |
ancestor-or-self::@*");
            }
            foreach(XmlNode node in nodes)
            {
                int nodePosition =
node.SelectNodes("preceding-sibling::*[local-name()='" + node.LocalName
+ "'
and namespace-uri()='" + node.NamespaceURI + "']").Count +1;
                path += "/" + GetQName(node) + "[" +
nodePosition.ToString() + "]";
            }
            if(baseNode.NodeType == XmlNodeType.Attribute)
                path += "/" + GetQName(baseNode);
            return(path);
        }

[1]
http://groups.google.com/groups?q=Getting+%22path%22+of+an+XmlNode++grou
p:mi
crosoft.public.dotnet.xml&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=%232rIkVm4BHA
.198
4%40tkmsftngp02&rnum=1

[Original message clipped]

| [aspngxml] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngxml.asp = JOIN/QUIT
| http://www.asplists.com/search = SEARCH Archives

Reply to this message...
 
 
System.Diagnostics.Debug
System.Xml.XmlNode
System.Xml.XmlNodeList
System.Xml.XmlNodeType




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification