XPath from XmlNode

I have a .NET XmlDocument and an XmlNode from that document.  Is there an easy way to generate the XPath to that node.  I don't think I can use wildcards because I have to get a unique path to the single node.
skip_sailorsAsked:
Who is Participating?
 
Bob LearnedCommented:
Example:



        private void Form1_Load(object sender, EventArgs e)
        {
            XmlDocument document = new XmlDocument();
            document.Load(@"c:\Backup\EDrive\log4net-1.2.10\log4net-1.2.10\xdocs\build.xml");
            XmlNode node = document.SelectSingleNode("//anakia");
 
            string xPath = this.BuildXPath(node);
 
            XmlNode test = document.SelectSingleNode(xPath);
        }
 
        private string BuildXPath(XmlNode node)
        {
            StringBuilder sb = new StringBuilder();
 
            while (node.ParentNode != null)
            {
                sb.Insert(0, "/" + node.Name);
                node = node.ParentNode;
            }
            return sb.ToString();
        }

Open in new window

0
 
PaulHewsCommented:
I don't think it's possible for a general "one size fits all" solution.  It's likely possible with foreknowledge of the XML structure.

What is the structure you are trying to parse in this situation?
0
 
Bob LearnedCommented:
XML:

<?xml version="1.0" ?>
<project name="xdocs" default="site" basedir=".">

      <property name="docs.src" value="./src" />
      <property name="docs.dest" value="../doc" />

      <property name="logging-site" value="../../../site/trunk" />

      <!-- Construct classpath for building the html pages -->
      <path id="site.classpath">
            <fileset dir="${logging-site}/lib">
                  <include name="*.jar" />
            </fileset>
      </path>

      <!-- ============================ -->
      <!-- ======= New targets ======== -->
      <!-- ============================ -->

      <target name="prepareSite">
            <available classname="org.apache.velocity.anakia.AnakiaTask" property="AnakiaTask.present">
                  <classpath refid="site.classpath" />
            </available>
      </target>

      <target name="checkSite" depends="prepareSite" unless="AnakiaTask.present">
            <echo>AnakiaTask is not present! Please check to make sure that velocity.jar is in your classpath.</echo>
      </target>

      <target name="site" depends="checkSite" if="AnakiaTask.present">
            <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask">
                  <classpath refid="site.classpath" />
            </taskdef>

            <mkdir dir="${docs.dest}/css" />
            <copy file="${logging-site}/docs/css/site.css" tofile="${docs.dest}/css/site.css" />
            
            <anakia
                  basedir="${docs.src}"
                  destdir="${docs.dest}/"
                  extension=".html"
                  style="site.vsl"
                  projectFile="stylesheets/project.xml"
                  excludes="empty.xml, anakia-project.xml, **/stylesheets/**"
                  includes="**/*.xml"
                  lastModifiedCheck="true"
                  templatePath="${docs.src}/stylesheets">
            </anakia>
            
      </target>

</project>

0
 
PaulHewsCommented:
The problem is that that doesn't work if there is more than one target/anakia nodes.  

<category>
<item>...</item>
<item>...</item>
</category>

You can't specify a unique path in this situation using category/item.  You can specify category/item[1] or category/item[2] (sample code below)

But this code will fail with a less regular XML structure, like ...

<category>
<otherthing>...</otherthing>
<item>...</item>
<item>...</item>
</category>
Private Function GetXPath(ByVal XNode As XmlNode) As String
        Dim Path As String = String.Empty
        Dim Index As Integer = -1
        If Not XNode.ParentNode.ParentNode Is Nothing Then
            Path = GetXPath(XNode.ParentNode)
            For i As Integer = 0 To XNode.ParentNode.ChildNodes.Count - 1
                Dim n As XmlNode = XNode.ParentNode.ChildNodes(i)
                If XNode Is n Then
                    Index = i
                    Exit For
                End If
            Next
        End If
        If Index > -1 Then
            Return Path & "/" & XNode.Name & String.Format("[{0}]", Index + 1)
        Else
            Return Path & "/" & XNode.Name
        End If
    End Function

Open in new window

0
 
skip_sailorsAuthor Commented:
Duplicate nodes shouldn't be a problem in my case.  I won't have to deal with the [x] position of the node.  Thank you for the help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.