简体   繁体   English

通过同级查找XML元素

[英]Find XML Element by their Sibling

How can I find the sibling of an XML Element with Visual Basic? 如何在Visual Basic中找到XML元素的同级元素? 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" . 另一个文本框显示“ Welcome”“ Content”元素。 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: 使用XmlDocument和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. 显然,由于主题可能不是唯一的,所以最好使用一些具有唯一ID的元素,或者可以按索引进行操作。 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. 然后,您可以为XML中的每个Mail元素加载一个Mail对象。 Because the ToString method is overriden to display the subject, you can just add the objects directly to the list box, for instance: 因为ToString方法被覆盖以显示主题,所以您可以直接将对象直接添加到列表框中,例如:

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: 然后,当选择列表框中的项目时,可以将所选项目转换为“ Mail类型并访问其属性,例如:

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: 但是,到那时,如果数据不是太大,使用XmlSerializer只是简单地将XML反序列化为对象就更容易了,例如,从创建定义整个XML文档的类开始,如下所示:

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): 然后像这样将XML加载到列表框中(其中xml是包含XML文档的字符串):

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: 或者,如果您想直接从XML文件读取而不是从字符串反序列化它:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM