|
-
Nov 24th, 2006, 04:01 AM
#1
Thread Starter
Addicted Member
[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 
-
Nov 24th, 2006, 04:43 AM
#2
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.
-
Nov 24th, 2006, 05:08 AM
#3
Thread Starter
Addicted Member
Re: 'Flatten' XML
Thanks for the reply.
I've come up with this now:
VB Code:
Option Explicit
Private Sub Command1_Click()
LoadDocument
End Sub
Public Sub LoadDocument()
Dim xDoc As DOMDocument
Set xDoc = New DOMDocument
xDoc.validateOnParse = False
If xDoc.Load("c:filename.xml") Then
DisplayNode xDoc.childNodes, ""
Else
' The document failed to load.
End If
End Sub
Private Sub DisplayNode(ByRef Nodes As IXMLDOMNodeList, _
ByVal p As String)
Dim xNode As IXMLDOMNode
For Each xNode In Nodes
If xNode.parentNode.nodeName <> Mid(p, InStrRev(p, "/", Len(p) - 1) + 1) Then
If xNode.nodeValue & "" <> "" Then
p = p & "/" & xNode.parentNode.nodeName & "/" & xNode.nodeValue
Else
p = p & "/" & xNode.parentNode.nodeName
End If
Debug.Print p
End If
If xNode.hasChildNodes Then
DisplayNode xNode.childNodes, p
End If
Next xNode
End Sub
Another light-hearted post from Guru 
-
Nov 24th, 2006, 05:10 AM
#4
Re: 'Flatten' XML
Whats this line for?
If xNode.parentNode.nodeName <> Mid(p, InStrRev(p, "/", Len(p) - 1) + 1) Then
-
Nov 24th, 2006, 05:53 AM
#5
Thread Starter
Addicted Member
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 
-
Nov 24th, 2006, 11:00 AM
#6
Re: [RESOLVED] 'Flatten' XML
VB Code:
Option Explicit
Private Sub Form_Load()
Dim xDoc As New MSXML2.DOMDocument
Dim nds As IXMLDOMNodeList
Dim nd As IXMLDOMNode
Dim cnt As Long
Dim sTmp As String
xDoc.Load "C:\test.xml"
Set nds = xDoc.selectNodes("//*")
For cnt = 0 To nds.length - 1
sTmp = GetPath(nds.Item(cnt))
Set nd = nds.Item(cnt).selectSingleNode("text()")
If Not (nd Is Nothing) Then sTmp = sTmp & "/" & nd.nodeValue
Debug.Print sTmp
Next
End Sub
Public Function GetPath(ByRef nd As IXMLDOMNode) As String
Dim sTmp As String
If Not (nd.parentNode Is Nothing) Then sTmp = GetPath(nd.parentNode) & "/" & nd.nodeName
GetPath = sTmp
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|