How can I find the sibling of an XML Element with Visual Basic? Let's say I have:
<Data>
<Mail>
<Subject>Welcome!</Subject>
<From>Antonios</From>
<Content>Welcome! How can I assist you?</Content>
</Mail>
<Mail>
<Subject>Test!</Subject>
<From>John</From>
<Content>Hello Friend!</Content>
</Mail>
</Data>
Now I have a list box that adds every Subject, so the list shows: Welcome! and Test! Now I want that, when I click on "Welcome!" , a Text Box shows the content of the "From" element of "Welcome!" and another Text Box shows the "Content" element of "Welcome" . In other words, I'm looking for the Sibling of a specific element .
You can do this in multiple ways. Here is how you can do it using XmlDocument
and XPath:
Dim doc As New XmlDocument()
Dim From As String = doc.SelectSingleNode("/Data/Mail[Subject='Welcome!']/From").InnerText
Dim Content As String = doc.SelectSingleNode("/Data/Mail[Subject='Welcome!']/Content").InnerText
Obviously, since the subject may not be unique, it would be better to use some element that is a unique ID, or you could do it by index. For instance, this selects from the first mail message:
Dim From As String = doc.SelectSingleNode("/Data/Mail[1]/From").InnerText
However, the best way to do something like this is to load all of the required data into memory up-front. Unless the amount of data is too great, which it doesn't sound like it is, that usually makes the most sense. So, for instance, I would recommend creating a data object that represents a mail message, for instance:
Public Class Mail
Public Property Subject() As String
Get
Return _subject
End Get
Set(ByVal value As String)
_subject = value
End Set
End Property
Private _subject As String
Public Property From() As String
Get
Return _from
End Get
Set(ByVal value As String)
_from = value
End Set
End Property
Private _from As String
Public Property Content() As String
Get
Return _content
End Get
Set(ByVal value As String)
_content = value
End Set
End Property
Private _content As String
Public Overrides Function ToString() As String
Return _subject
End Function
End Class
Then, you can load one Mail
object for each Mail element in the XML. Because the ToString
method is overriden to display the subject, you can just add the objects directly to the list box, for instance:
Dim doc As New XmlDocument()
For Each node As XmlNode In doc.SelectNodes("/Data/Mail")
Dim mail As New Mail()
mail.Subject = node.SelectSingleNode("Subject").InnerText
mail.From = node.SelectSingleNode("From").InnerText
mail.Content = node.SelectSingleNode("Content").InnerText
ListBox1.Items.Add(mail)
Next
Then, when an item in the list box is selected, you can cast the selected item to the Mail
type and access its properties, for instance:
Dim mail As Mail = CType(ListBox1.SelectedItem, Mail)
Label1.Text = mail.From
Label2.Text = mail.Content
However, at that point, if the data is not too large, it's even easier to just use the XmlSerializer
to simply deserialize the XML into an object, for instance, start by creating a class that defines the entire XML document, like this:
Public Class Data
<XmlElement("Mail")> _
Public Property Mails() As List(Of Mail)
Get
Return _mails
End Get
Set(ByVal value As List(Of Mail))
_mails = value
End Set
End Property
Private _mails As List(Of Mail)
End Class
Then load the XML into the list box like this (where xml
is a string containing the XML document):
Dim serializer As New XmlSerializer(GetType(Data))
Dim reader As New StringReader(xml)
Dim data As Data = CType(serializer.Deserialize(reader), Data)
ListBox1.Items.AddRange(data.Mails.ToArray())
Or, if you want to read from an XML file directly instead of deserializing it from a string:
Dim serializer As New XmlSerializer(GetType(Data))
Using stream As New FileStream("Test.xml", FileMode.Open)
Dim data As Data = CType(serializer.Deserialize(stream), Data)
ListBox1.Items.AddRange(data.Mails.ToArray())
End Using
To answer your second question that you asked in your comment below, to delete a given mail message, you could do it like this:
Dim node As XmlNode = doc.SelectSingleNode("/Data/Mail[Subject='Welcome!']")
node.ParentNode.RemoveChild(node)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.