Reputation: 3
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
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
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
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