2012-08-14 115 views
0

如何使用Visual Basic找到XML元素的同级?比方说,我有:通过其兄弟找到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> 

现在我有一个列表框,增加了每一个主题,所以列表显示:欢迎您!测试! 现在我想,当我点击“欢迎!”,文本框显示“From”元素的内容“Welcome!”和另一个文本框显示“内容”元素“欢迎”。 换句话说,我正在寻找特定元素的兄弟姐妹。

回答

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 

然后,你可以加载一个Mail对象为XML中的每个邮件元素。因为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文档的类,如下所示:

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) 
+0

谢谢!正是我在找什么!你是否也知道(所以我不需要创建一个新帖子)如何删除某个 Parent与孩子? – Antonios 2012-08-14 18:54:26

+0

@Antonios我更新了我的答案,也回答你的第二个问题。但是,将来,最好单独提出每个问题。对于其他人在未来寻找同一问题的答案时更有用,它可以帮助您获得更多的信誉来启动。 – 2012-08-14 19:07:53

+0

是的,你是对的^^ – Antonios 2012-08-14 19:10:02