1

I have a huge XML File (20'000 Rows) and i want to read some Data out of it. I have written an Routine by now. My Question is, is there a way to make it look better? Because i think that's an ugly way to get the Data out of the File.

This is the Structure of my XML File

<List
<Header>
</>
<Root>
    <Items>
        <Object>
            <Items>
                <Object>
                    <Items>
                        <Object>
                            <Items>
                                <Object>
                                    <IoItems>
                                        <IoObject>
                                        </>
                                    </>
                                </>
                            </>
                            <IoItems>                           
                                <IoObject>
                                </>
                            </>
                        </>
                        <Object>
                        </>
                        <Object>
                        </>
                        <Object>
                        </>
                    </> 
                </> 
                <Object>
                    //Like the Object above
                </>
                <StructureObject>
                    //Like the Object above
                </>
            </> 
        </> 
    </> 
</> 

And my Code looks like that:

Dim myXMLDoc As New XmlDocument
        Dim Node As XmlNode
        Dim Node2 As XmlNode
        Dim Node3 As XmlNode
        Dim Node4 As XmlNode
        Dim Node5 As XmlNode
        Dim Node6 As XmlNode
        Dim Node7 As XmlNode
        Dim Node8 As XmlNode
        Dim Node9 As XmlNode
        Dim Node10 As XmlNode
        Dim Node11 As XmlNode

        myXMLDoc.Load("H:\Data.xml")
        Dim root As XmlNode = myXMLDoc.GetElementsByTagName("Root")(0)

        For Each Node In root.ChildNodes
            If Node.Name = "Items" Then
                For Each Node2 In Node.ChildNodes
                    If Node2.Name = "Object" Then
                        For Each Node3 In Node2.ChildNodes
                            If Node3.Name = "Items" Then
                                For Each Node4 In Node3.ChildNodes
                                    If Node4.Name = "Object" Then
                                        For Each Node5 In Node4.ChildNodes
                                            If Node5.Name = "Items" Then
                                                For Each Node6 In Node5.ChildNodes
                                                    If Node6.Name = "Object" Then
                                                        For Each Node7 In Node6.ChildNodes
                                                            If Node7.Name = "Items" Then
                                                                For Each Node8 In Node6.ChildNodes
                                                                    If Node8.Name = "Object" Then
                                                                        For Each Node9 In Node8.ChildNodes
                                                                            If Node9.Name = "IoItems" Then
                                                                                For Each Node10 In Node9.ChildNodes
                                                                                    If Node10.Name = "IoObject" Then
                                                                                        MsgBox(Node10.Value)
                                                                                    End If
                                                                                Next
                                                                            End If
                                                                        Next
                                                                    End If
                                                                Next
                                                            ElseIf Node6.Name = "IoItems" Then
                                                                For Each Node11 In Node6.ChildNodes
                                                                    If Node11.Name = "IoObject" Then
                                                                        MsgBox(Node11.Value)
                                                                    End If
                                                                Next
                                                            End If
                                                        Next
                                                    End If
                                                Next
                                            End If
                                        Next
                                    End If
                                Next
                            End If
                        Next
                    End If
                Next
            End If         
        Next
Moosli
  • 3,140
  • 2
  • 19
  • 45
  • 1
    Subjective questions (what do you mean by "better") are not a good fit for [SO]. However, in that case I would use a single XPath expression to go directly to the value (or fail is something is missing, without specific information about what – which your approach could do (in `else` clauses). I would also split into multiple functions. – Richard Feb 02 '15 at 10:27
  • 2
    Please don't invent your own XML syntax. That makes it hard to provide an answer that has actually been *tested*, because we have to translate your sample back to real XML. Better use the actual XML right from the start. Cutting out the unnecessary parts is even easier for you than renaming all closing tags to `>`. – Tomalak Feb 02 '15 at 10:50

3 Answers3

2

Your attempt should tell you instantly that you are doing something wrong. If you seem to need 4 or more source code nesting levels you should lean back and reflect on what you are actually trying to do. You should definitely not go on and create code that is nested twenty-one levels deep.

You are missing XPath, the XML selection language. It can select the nodes you are interested in quite easily.

Dim myXMLDoc As New XmlDocument
' load some XML into myXMLDoc...

For Each ioObject As XmlNode In myXMLDoc.SelectNodes("//IoObject")
    Console.WriteLine(ioObject.InnerXml)
Next ioObject

You can define a more complex path to select exactly the nodes you want.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
2

The easiest way to handle XML in VB.NET is to use XElement instead of XmlDocument and XML literals (at least most of the time).

So to get all <IoObject> elements, simply use

Dim xml = XElement.Load("H:\Data.xml")

For Each node In xml...<IoObject>
    MsgBox(node.Value)
Next
sloth
  • 99,095
  • 21
  • 171
  • 219
  • Is this capable of replacing XPath? – Tomalak Feb 02 '15 at 13:23
  • @Tomalak It depends. I guess you could rewrite most XPath queries with Linq and XML literal; and usually I avoid the `XmlDocument` class in favour of the newer `XElement`. Special cases like reading comments and processing instruction aside, I think I never had to use XPath in VB.NET. But I wouldn't be angry if `XElement` would support XPath, too :-) – sloth Feb 02 '15 at 13:57
  • Ah, so this is a [LINQ operator](http://stackoverflow.com/questions/5883491/vb-net-triple-dot-syntax-for-linq-to-xml). I didn't know. – Tomalak Feb 02 '15 at 14:49
1

If myXMLDoc is an XMLDOM object, you can find each chain of tags so:

Set nodes = root.selectNodes("Items/Object/Items/Object/.../IoObject")
For Each Node In nodes
    ' do something
Next

It works in VBScript for CreateObject("MSXML.DOMDocument"). Not checked it in VB.NET.

Vasily Ryabov
  • 9,386
  • 6
  • 25
  • 78