通过他们的兄弟姐妹查找XML元素

时间:2012-08-14 10:05:22

标签: xml vb.net siblings

如何使用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>

现在我有一个添加每个主题的列表框,因此列表显示:欢迎!测试! 现在我希望如此,当我点击“欢迎!”时,文本框会显示“欢迎!”“来自”元素的内容。和另一个文本框显示“欢迎”“内容”元素。 换句话说,我正在寻找特定元素的兄弟姐妹

1 个答案:

答案 0 :(得分:1)

您可以通过多种方式执行此操作。以下是使用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

显然,由于主题可能不是唯一的,最好使用一些唯一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

然而,在那时,如果数据不是太大,那么使用XmlSerializer简单地将XML反序列化为对象就更容易了,例如,首先创建一个定义整个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

然后将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)