Results 1 to 6 of 6

Thread: [RESOLVED] 'Flatten' XML

  1. #1

    Thread Starter
    Addicted Member Guru's Avatar
    Join Date
    May 2000
    Location
    sulking in the cupboard under the stairs
    Posts
    237

    Resolved [RESOLVED] 'Flatten' XML

    I want to flatten XML so the full path of each element is easily visible.
    I'm sure this sort of thing must have been done before:

    so,
    <Order>
    <OrderHeader>
    <OrderNumber>
    <BuyerOrderNumber>ABC123</BuyerOrderNumber>
    <SellerOrderNumber>XYZ456</SellerOrderNumber>
    </OrderNumber>
    <OrderIssueDate>20061120T03:05:17-05:00</OrderIssueDate>
    <OrderReferences>
    <AccountCode>
    <Reference>
    <RefNum>RRRRR</RefNum>
    </Reference>
    </AccountCode>
    </OrderReferences>
    </OrderHeader>
    </Order>

    produces:

    Order
    Order/OrderHeader
    Order/OrderHeader/OrderNumber
    Order/OrderHeader/OrderNumber/BuyerOrderNumber/ABC123
    Order/OrderHeader/OrderNumber/SellerOrderNumber/XYZ456
    Order/OrderHeader/OrderIssueDate/20061120T03:05:17-05:00
    Order/OrderHeader/OrderReferences
    Order/OrderHeader/OrderReferences/AccountCode
    Order/OrderHeader/OrderReferences/AccountCode/Reference
    Order/OrderHeader/OrderReferences/AccountCode/Reference/RefNum/RRRRR

    Thanks
    Another light-hearted post from Guru

  2. #2
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: 'Flatten' XML

    I have no 'clever' way off the top of my head, but you could do something like this:

    (pseudo code, but the class and member names should be right)
    Code:
    scan_nodes(root_node, optional path)
    {
      if (path is null):
        string path = root_node.nodeName;
      
      for each Node child in root_node.childNodes {
        if (child.nodeType == Node.TEXT_NODE):
          output path & '/' & child.data;
        else if (child.nodeType == Node.ELEMENT_NODE):
          output path & '/' & child.nodeName;
        
        if (child.hasChildNodes()):
          scan_nodes(child, path & '/' & child.nodeName);
      }
    }
    
    # Usage:
    scan_nodes(xml_doc.documentElement);
    Edit: fixed to handle text nodes properly.
    Last edited by penagate; Nov 24th, 2006 at 04:48 AM.

  3. #3

    Thread Starter
    Addicted Member Guru's Avatar
    Join Date
    May 2000
    Location
    sulking in the cupboard under the stairs
    Posts
    237

    Re: 'Flatten' XML

    Thanks for the reply.

    I've come up with this now:


    VB Code:
    1. Option Explicit
    2.  
    3. Private Sub Command1_Click()
    4. LoadDocument
    5. End Sub
    6.  
    7. Public Sub LoadDocument()
    8. Dim xDoc As DOMDocument
    9. Set xDoc = New DOMDocument
    10. xDoc.validateOnParse = False
    11. If xDoc.Load("c:filename.xml") Then
    12.    DisplayNode xDoc.childNodes,  ""
    13. Else
    14.    ' The document failed to load.
    15. End If
    16. End Sub
    17.  
    18. Private Sub DisplayNode(ByRef Nodes As IXMLDOMNodeList, _
    19.   ByVal p As String)
    20.  
    21.    Dim xNode As IXMLDOMNode
    22.    For Each xNode In Nodes
    23.      
    24.             If xNode.parentNode.nodeName <> Mid(p, InStrRev(p, "/", Len(p) - 1) + 1) Then
    25.                 If xNode.nodeValue & "" <> "" Then
    26.                     p = p & "/" & xNode.parentNode.nodeName & "/" & xNode.nodeValue
    27.                 Else
    28.                     p = p & "/" & xNode.parentNode.nodeName
    29.                 End If
    30.            
    31.             Debug.Print p
    32.             End If
    33.      
    34.  
    35.       If xNode.hasChildNodes Then
    36.          DisplayNode xNode.childNodes,  p
    37.       End If
    38.    Next xNode
    39. End Sub
    Another light-hearted post from Guru

  4. #4
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: 'Flatten' XML

    Whats this line for?

    If xNode.parentNode.nodeName <> Mid(p, InStrRev(p, "/", Len(p) - 1) + 1) Then

  5. #5

    Thread Starter
    Addicted Member Guru's Avatar
    Join Date
    May 2000
    Location
    sulking in the cupboard under the stairs
    Posts
    237

    Re: 'Flatten' XML

    It's just a frig really.

    For some reason, when going back down the nodes it was appending the node name again

    /#document
    /#document/Order
    /#document/Order/OrderHeader
    /#document/Order/OrderHeader/OrderNumber
    /#document/Order/OrderHeader/OrderNumber/BuyerOrderNumber/ABC123
    /#document/Order/OrderHeader/OrderNumber/OrderNumber
    /#document/Order/OrderHeader/OrderHeader
    /#document/Order/OrderHeader/OrderHeader/OrderIssueDate/20061120T03:05:17-05:00
    /#document/Order/OrderHeader/OrderHeader/OrderHeader


    The 'if' was just to stop that happening.
    Not perfect because ther could be nodes with the same name a the parent node, but it's good enough for what I need at the moment
    Another light-hearted post from Guru

  6. #6
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: [RESOLVED] 'Flatten' XML

    VB Code:
    1. Option Explicit
    2.  
    3. Private Sub Form_Load()
    4. Dim xDoc As New MSXML2.DOMDocument
    5. Dim nds As IXMLDOMNodeList
    6. Dim nd As IXMLDOMNode
    7. Dim cnt As Long
    8. Dim sTmp As String
    9.  
    10.    xDoc.Load "C:\test.xml"
    11.    Set nds = xDoc.selectNodes("//*")
    12.    
    13.    For cnt = 0 To nds.length - 1
    14.       sTmp = GetPath(nds.Item(cnt))
    15.       Set nd = nds.Item(cnt).selectSingleNode("text()")
    16.       If Not (nd Is Nothing) Then sTmp = sTmp & "/" & nd.nodeValue
    17.  
    18.       Debug.Print sTmp
    19.    Next
    20. End Sub
    21.  
    22. Public Function GetPath(ByRef nd As IXMLDOMNode) As String
    23. Dim sTmp As String
    24.  
    25.    If Not (nd.parentNode Is Nothing) Then sTmp = GetPath(nd.parentNode) & "/" & nd.nodeName
    26.    GetPath = sTmp
    27. End Function

    Output:
    /Order
    /Order/OrderHeader
    /Order/OrderHeader/OrderNumber
    /Order/OrderHeader/OrderNumber/BuyerOrderNumber/ABC123
    /Order/OrderHeader/OrderNumber/SellerOrderNumber/XYZ456
    /Order/OrderHeader/OrderIssueDate/20061120T03:05:17-05:00
    /Order/OrderHeader/OrderReferences
    /Order/OrderHeader/OrderReferences/AccountCode
    /Order/OrderHeader/OrderReferences/AccountCode/Reference
    /Order/OrderHeader/OrderReferences/AccountCode/Reference/RefNum/RRRRR
    Last edited by leinad31; Nov 24th, 2006 at 11:10 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width