0

如何使用 Visual Basic 找到 XML 元素的兄弟?假设我有:

<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>

现在我有一个添加每个主题的列表框,所以列表显示:欢迎!测试! 现在我想要那个,当我点击“欢迎!”时 ,一个文本框显示 “欢迎”的“发件人”元素的内容。另一个文本框显示了"Welcome"的"Content"元素。换句话说,我正在寻找特定元素的 Sibling

4

1 回答 1

1

您可以通过多种方式执行此操作。以下是使用XmlDocumentXPath 的方法:

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

显然,由于主题可能不是唯一的,因此最好使用一些作为唯一 ID 的元素,或者您可以通过索引来完成。例如,这从第一封邮件中选择:

Dim From As String = doc.SelectSingleNode("/Data/Mail[1]/From").InnerText

但是,执行此类操作的最佳方法是将所有需要的数据预先加载到内存中。除非数据量太大,听起来不像,否则这通常是最有意义的。因此,例如,我建议创建一个表示邮件消息的数据对象,例如:

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

然后,您可以为 XML 中的每个 Mail 元素加载一个Mail对象。因为该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

然后,当列表框中的项目被选中时,您可以将所选项目强制转换为Mail类型并访问其属性,例如:

Dim mail As Mail = CType(ListBox1.SelectedItem, Mail)
Label1.Text = mail.From
Label2.Text = mail.Content

但是,此时,如果数据不是太大,使用 将XmlSerializerXML 简单地反序列化为对象会更容易,例如,首先创建一个定义整个 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

然后像这样将 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())

或者,如果您想直接从 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

要回答您在下面的评论中提出的第二个问题,要删除给定的邮件,您可以这样做:

Dim node As XmlNode = doc.SelectSingleNode("/Data/Mail[Subject='Welcome!']")
node.ParentNode.RemoveChild(node)
于 2012-08-14T12:06:29.387 回答