user4740515
user4740515

Reputation: 3

Retrieve certain data from XML File

My XML File:

<?xml version="1.0" encoding="utf-8"?>
<DisksLibrary>
  <Disk>
    <DiskName>Test</DiskName>
    <DiskPath>testpath</DiskPath>
  </Disk>
  <Disk>
    <DiskName>Test1</DiskName>
    <DiskPath>testpath1</DiskPath>
  </Disk>
  <Disk>
    <DiskName>Test2</DiskName>
    <DiskPath>testpath2</DiskPath>
  </Disk>
</DisksLibrary>

I was wondering since I have multiple tags with the same name such as and in My XML File, is it possible to retrieve a particular set of data from the XML File? For example, if I want to retrieve the DiskPath innertext which is under the same set as the one with the InnerText of "Test". In other words, the DiskPath I should retrieve is "testpath1". How do I ensure it does not confuse with other DiskPath innertext?

I tried searching online but either no solution was provided or the solution provided does not work for me. I found one solution which seem to work but after reading the code I don't think it works if there are multiple tags with the same name.

The solution I found which I am not sure if it resolves my problem is:

Dim document As XmlReader = New XmlTextReader("MyXML.xml")

While (document.Read())
    Dim type = document.NodeType
    If (type = XmlNodeType.Element) Then
        If (document.Name = "FirstName") Then
            TextBox1.Text = document.ReadInnerXml.ToString()
        End If

        If (document.Name = "LastName") Then
            TextBox2.Text = document.ReadInnerXml.ToString()
        End If
    End If
End While

Thank you for your help. Appreciate it.

Upvotes: 0

Views: 116

Answers (3)

Mark
Mark

Reputation: 8150

Here's another option using LINQ to XML and XML literals:

Dim document = XDocument.Load("MyXML.xml")
Dim path As String = (
    From disk In document...<Disk>
    Where disk.<DiskName>.Value = "Test"
    Select disk.<DiskPath>.Value
).SingleOrDefault()

path will either be the value of the matching <DiskPath> element, or Nothing if not found.

Upvotes: 0

Shar1er80
Shar1er80

Reputation: 9041

I would consider parameterizing the XPath approach to make it scalable.

Imports System.Xml

Module Module1
    Sub Main()
        Dim xml As String = _
            "<?xml version=""1.0"" encoding=""utf-8""?>" & _
            "<DisksLibrary>" & _
            "  <Disk>" & _
            "    <DiskName>Test1</DiskName>" & _
            "    <DiskPath>testpath1</DiskPath>" & _
            "  </Disk>" & _
            "  <Disk>" & _
            "    <DiskName>Test2</DiskName>" & _
            "    <DiskPath>testpath2</DiskPath>" & _
            "  </Disk>" & _
            "  <Disk>" & _
            "    <DiskName>Test3</DiskName>" & _
            "    <DiskPath>testpath3</DiskPath>" & _
            "  </Disk>" & _
            "</DisksLibrary>"
        Dim doc As New XmlDocument
        doc.LoadXml(xml)

        For i = 1 To 4
            Dim foundNode = FindSiblingNode(doc, "Test" & i, "DiskPath")
            Console.WriteLine(If(Not foundNode Is Nothing, foundNode.InnerText, "Node not found"))
        Next

        Console.ReadLine()
    End Sub

    Public Function FindSiblingNode(ByVal doc As XmlDocument, _
                                    ByVal siblingNodeInnerText As String, _
                                    ByVal searchNodeName As String) As XmlNode
        Return doc.SelectSingleNode(String.Format("/DisksLibrary/Disk[DiskName='{0}']/{1}", siblingNodeInnerText, searchNodeName))
    End Function
End Module

Results:

testpath1
testpath2
testpath3
Node not found

Upvotes: 1

Wibbler
Wibbler

Reputation: 1045

Reading about XPath and Predicates (http://www.w3schools.com/xpath/xpath_syntax.asp) would be very useful to you. In your instance you want to return the inner text of any "DiskPath" elements whose sibling "DiskName" has a value of "Test". As Styxxy described the XPath /DisksLibrary/Disk[DiskName="Test"]/DiskPath would achieve this:

        Dim doc As New XmlDocument
        Dim targetPath As String
        doc.Load("MyXML.xml")
        Dim foundNode As XmlNode = doc.SelectSingleNode("/DisksLibrary/Disk[DiskName='Test']/DiskPath")
        If Not (foundNode Is Nothing) Then
            targetPath = foundNode.InnerText
        End If

Upvotes: 1

Related Questions