Share on Facebook
Welcome to MSDN Blogs Sign in | Join | Help

Getting Path from an XmlNode

I actually posted this about a year ago, but just ran across a need for the snippet again.  Thought posting here might benefit others as well as serve as a repository.  This allows you to get the path of a given XML node, as well as getting the qualified name of the node.

  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 is a misnomer here, but the current node belongs in a
non-prefixed namespace...
      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);
  }

Published Thursday, April 10, 2003 12:02 PM by kaevans

Comments

# re: Getting Path from an XmlNode

Sunday, February 29, 2004 4:03 PM by Jay Patel
What about the inverse situation?

I want to put an element/value at a specified XPath location in an xml document that may or may not contain the element. Is there a way to do this without jumping through hoops?

# re: Getting Path from an XmlNode

Sunday, February 29, 2004 4:13 PM by Jay Patel
What about the inverse situation?

I want to put an element/value at a specified XPath location in an xml document that may or may not contain the element. Is there a way to do this without jumping through hoops?

# re: Getting Path from an XmlNode

Monday, March 01, 2004 7:01 AM by Kirk Allen Evans
You can use the DOM for this.

XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode node = doc.SelectSingleNode("/foo/bar[@baz='test']");
if(null == bar)
{
XmlNode barr = foo.AppendChild(doc.CreateElement("bar"));
XmlAttribute a = bar.Attributes.Add(doc.CreateAttribute("baz"));
a.Value = "test";
}

# re: Getting Path from an XmlNode

Friday, July 09, 2004 5:24 PM by Aaron
I'm curious what's going on with this XPath statement, "ancestor-or-self::* |
ancestor-or-self::@*". In my app it keeps on crashing giving me a system error.

# re: Getting Path from an XmlNode

Saturday, July 10, 2004 7:09 PM by Kirk Allen Evans
The statement selects along the ancestor node, including the current context node, looking for any elements or attributes.

Sounds like a pretty ambiguous description of the fault. Have you tried debugging to any reasonable level of isolation? There are several versions of the .NET framework available (beta, 1.0, 1.1, 2.0 beta), anything beta is unsupported. If you are querying a huge document (huge being absolutely relative to your system's RAM and avialable memory w.r.t. other running applications), then you might be receiving some type of out of memory exception?

Let's remember to be safe out there, people... don't try to run XPath statements over 5 Gig documents. It just doesn't make sense. You wouldn't pull back 50,000 rows from a database and filter on the client side, you would limit the amount of data you pull back from the database. Amazingly, the same rules of conservative memory usage apply to XML: there are 2 models, the DOM and the pull-based XmlReader parser... the DOM pulls everything into memory, the XmlReader reads one node at a time.

# re: Getting Path from an XmlNode

Saturday, July 10, 2004 9:06 PM by Aaron
Wow, thanks for the quick response. I'm running .NET 1.1.4322.573. If I go in deeper to see what the exception is I get this: "System.Xml.XPath.XPathException

The expression passed to this method should result in a NodeSet."

The XmlDocument only has 3 nodes in it for testing.

The real part of the XPath that my app doesn't seem to like is, "ancestor-or-self::@*". The other half of the or works fine by itself. I hope that's some more information for you.

By the way, these msdn blogs are pretty sweet. You guys always seem to have goo dtings to say.
New Comments to this post are disabled
 
Page view tracker