All available xpath in XML document

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • oscar2
    New Member
    • May 2010
    • 9

    All available xpath in XML document

    I am using vb.net 2010 to get data from XML file, I was wondering if there is any way to find and print all available xpath of all nodes in the document. For example:
    XML file is like :
    Code:
    <CATALOG>
      <CD>
        <TITLE>Empire Burlesque</TITLE>
        <ARTIST>Bob Dylan</ARTIST>
      </CD>
      <CD>
        <TITLE>Hide your heart</TITLE>
        <ARTIST>Bonnie Tyler</ARTIST>
      </CD>
    The result should be something like :

    /CATALOG
    /CATALOG/CD
    /CATALOG/CD/TITLE
    /CATALOG/CD/ARTIST

    I hope I'm clear enough..
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    I was wondering if there is any way to find and print all available xpath of all nodes in the document.
    there’s more than just those 4 XPaths. you can have relative XPaths, you can have XPaths with conditions, with selectors, etc. etc.

    what you possibly mean is a document tree representation.

    Comment

    • oscar2
      New Member
      • May 2010
      • 9

      #3
      In fact I need those 4 paths and of course if there is another node inside say TITLE I need a path to that node as well. All paths should start from the Root node CATALOG in this case. It might be worth mentioning that I will then feed those paths to a list to give the user an easy way to select the node or node-set to be modified.
      Thanks :)

      Comment

      • jkmyoung
        Recognized Expert Top Contributor
        • Mar 2006
        • 2057

        #4
        I've done this with xslt before; it's possible to do it with other languages as well. It's recursion; Pseudocode:
        Code:
        Start at document level. 
        call f(rootnode, "")
        
        
        f(Node n, String s){
          For each child node of n {
            path = s + \ + node name
            print path
            child.f(n, path)
          }
        }
        Last edited by jkmyoung; May 27 '10, 01:15 PM. Reason: added node to function.

        Comment

        • oscar2
          New Member
          • May 2010
          • 9

          #5
          Thanks I am working on something similar.. will post here if I get the same result with VB.net
          Thanks again

          Comment

          • oscar2
            New Member
            • May 2010
            • 9

            #6
            I am working with this right now, This recursive sub can easily find path of all children but it will miss any sibling!

            Code:
            Public Class Form1
                Public path As String
            
                Private Sub cmdRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRun.Click
                    Dim xDoc As XmlDocument = New XmlDocument
                    xDoc.Load("C:\Temp\file.xml")
                    Dim node As XmlNode = xDoc.SelectSingleNode("/catalog")
                    path = node.Name
                    GetPath(node)
                End Sub
            
                Private Sub GetPath(ByVal node As XmlNode)
                    lst.Items.Add(path)
            
                    If node.HasChildNodes = True Then  ' <==> If Not node.NodeType = XmlNodeType.Text Then 
                        path = path & "/" & node.FirstChild.Name
                        node = node.FirstChild
                        GetPath(node)
                    End If
                End Sub
            
            End Class
            Hope someone can build on this and give some insights.

            Comment

            • jkmyoung
              Recognized Expert Top Contributor
              • Mar 2006
              • 2057

              #7
              Lines 15 - 19.
              You're only attacking the first child. You should be able to put just
              if node.HasChildNo des
              (remove the = true)

              I'm not sure of the exact syntax in vb, but it goes something like:
              Code:
              dim children = node.ChildNodes
              For i = 0 To children.length
                dim child = children[i]
                path = path & "/" & child.Name 
                GetPath(child) 
              Next i

              Comment

              • oscar2
                New Member
                • May 2010
                • 9

                #8
                Thanks.. i working on it :)

                Comment

                • jkmyoung
                  Recognized Expert Top Contributor
                  • Mar 2006
                  • 2057

                  #9
                  Note, edited the above code, accidentally put GetPath(node) when I meant
                  GetPath(child)

                  Comment

                  • oscar2
                    New Member
                    • May 2010
                    • 9

                    #10
                    It is rather confusing right :)
                    Now at last I got it to work. Check this out:

                    Code:
                    Sub GetPaths(ByVal node As Xml.XmlNode, ByVal paths As List(Of String), Optional ByVal path As String = "")
                            path &= "/" & node.Name
                            If Not paths.Contains(path) Then
                                paths.Add(path)
                                lstPaths.Items.Add(path)
                            End If
                            For Each child As Xml.XmlNode In node.ChildNodes
                                If child.NodeType = Xml.XmlNodeType.Element Then
                                    GetPaths(child, paths, path)
                                End If
                            Next
                        End Sub
                    and...

                    Code:
                    Dim xDoc As New XmlDocument
                    Dim paths As New List(Of String)
                    GetPaths(xDoc.DocumentElement, paths)
                    lstPaths.SelectedIndex = 0

                    Problem solved ;)

                    Comment

                    Working...