如何同时检索子XML节点和父XML节点的值?

如何同时检索子XML节点和父XML节点的值?,xml,vb.net,winforms,treeview,Xml,Vb.net,Winforms,Treeview,示例XML <Drawer_System_1> <DrawerSystemID>1</DrawerSystemID> <DrawerSysName>Drawer_System_1</DrawerSysName> <DrawerSysLocation>North Wall (2nd from left)</DrawerSysLocation> <Drawers> <DrawerID&g

示例XML

<Drawer_System_1>
 <DrawerSystemID>1</DrawerSystemID>
 <DrawerSysName>Drawer_System_1</DrawerSysName>
 <DrawerSysLocation>North Wall (2nd from left)</DrawerSysLocation>
 <Drawers>
  <DrawerID>1-01</DrawerID>`enter code here`
  <Contents>Contents of Drawer 1-01</Contents>
 </Drawers>
 <Drawers>
  <DrawerID>1-02</DrawerID>
  <Contents>Contents of Drawer 1-02</Contents>
 </Drawers>
</Drawer_System_1>

我按照建议重新构造了XML文件。我得到了正确显示抽屉系统的信息。在选择抽屉系统时,是否有办法在第二个列表框(或其他类型的控件)中显示有关各个抽屉的信息?此外,由于某些原因,我的图像不会显示在PictureBox中。

听起来是一种奇怪的方式。我认为,如果您将XML加载到TreeView控件中,那么您将把所有必要的数据存储到
TreeNode.Tag
属性中,或者存储到TreeView之外内存中的某个数据结构中,这样当他们选择一个节点时,您就不必返回XML来获取子元素的数据。但是,如果您想这样做,这里有一种从XML中读取数据的方法:

Dim xmlText As String = "<Drawer_System_1>...</Drawer_System_1>..."
Dim doc As New XmlDocument()
doc.LoadXml(xmlText)
Dim parentNode As XmlNode = doc.SelectSingleNode("//Drawer_System_1")
Dim drawerSystemID As String = parentNode.SelectSingleNode("DrawerSystemID").InnerText
Dim drawerSysName As String = parentNode.SelectSingleNode("DrawerSysName").InnerText
Dim drawerSysLocation As String = parentNode.SelectSingleNode("DrawerSysLocation").InnerText
然后,当您为抽屉系统创建“TreeNode”时,您可以将其标记如下:

Public Class DrawerSystem
    Public ID As String
    Public Name As String
    Public Location As String
End Class
Private Sub AddNode(drawerSystem As DrawerSystem)
    Dim node As TreeNode = TreeView1.Nodes.Add(drawerSystem.Name)
    node.Tag = drawerSystem
End Sub
Dim drawerSystem As DrawerSystem = CType(e.Node.Tag, DrawerSystem)
Label1.Text = drawerSystem.ID
Label2.Text = drawerSystem.Location
Public Class My_LEGO_Elements
    Private Sub My_LEGO_Elements_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim serializer As New SimpleXmlSerializer()
        Dim data As LegoElementsData = serializer.DeSerialize(Of LegoElementsData)(File.ReadAllText("C:\Users\Steven\Documents\Visual Studio 2012\Projects\My_LEGO_Elements\My_LEGO_Elements\Drawer_Systems_3.xml"))
        ListBox1.Items.AddRange(data.DrawerSystems.ToArray())
    End Sub

    Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedValueChanged
        Dim drawerSystem As DrawerSystem = CType(ListBox1.SelectedItem, DrawerSystem)
        Label1.Text = drawerSystem.Id
        Label2.Text = drawerSystem.Location
        Label3.Text = drawerSystem.Name
        ListBox2.Items.Clear()
        ListBox2.Items.AddRange(drawerSystem.Drawers.ToArray())
    End Sub
End Class
然后,例如,在单击或选择节点时,您可以如下方式检索该对象:

Public Class DrawerSystem
    Public ID As String
    Public Name As String
    Public Location As String
End Class
Private Sub AddNode(drawerSystem As DrawerSystem)
    Dim node As TreeNode = TreeView1.Nodes.Add(drawerSystem.Name)
    node.Tag = drawerSystem
End Sub
Dim drawerSystem As DrawerSystem = CType(e.Node.Tag, DrawerSystem)
Label1.Text = drawerSystem.ID
Label2.Text = drawerSystem.Location
Public Class My_LEGO_Elements
    Private Sub My_LEGO_Elements_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim serializer As New SimpleXmlSerializer()
        Dim data As LegoElementsData = serializer.DeSerialize(Of LegoElementsData)(File.ReadAllText("C:\Users\Steven\Documents\Visual Studio 2012\Projects\My_LEGO_Elements\My_LEGO_Elements\Drawer_Systems_3.xml"))
        ListBox1.Items.AddRange(data.DrawerSystems.ToArray())
    End Sub

    Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedValueChanged
        Dim drawerSystem As DrawerSystem = CType(ListBox1.SelectedItem, DrawerSystem)
        Label1.Text = drawerSystem.Id
        Label2.Text = drawerSystem.Location
        Label3.Text = drawerSystem.Name
        ListBox2.Items.Clear()
        ListBox2.Items.AddRange(drawerSystem.Drawers.ToArray())
    End Sub
End Class
我不明白为什么需要在树视图中以相同的层次结构显示XML中的所有元素。看起来一个简单的抽屉系统列表就足够了。然后,当选择列表中的某个项目时,您可以在其他控件中显示该抽屉系统的所有详细信息。此外,我建议只将XML反序列化为匹配的数据结构,而不是尝试循环遍历XML。例如,如果您像这样重新格式化XML(只是为了使其更有利于反序列化):

然后,为了让您的生活更轻松,我建议您创建自己的序列化程序类,以简化该过程,例如:

Public Class SimpleXmlSerializer
    Public Function Serialize(ByVal objectToSerialize As Object) As String
        Dim serializer As XmlSerializer = New XmlSerializer(objectToSerialize.GetType())
        Using stream As MemoryStream = New MemoryStream()
            Dim namespaces As XmlSerializerNamespaces = New XmlSerializerNamespaces()
            namespaces.Add("", "")
            serializer.Serialize(stream, objectToSerialize, namespaces)
            Using reader As StreamReader = New StreamReader(stream)
                stream.Position = 0
                Return reader.ReadToEnd()
            End Using
        End Using
    End Function

    Public Function DeSerialize(Of T)(ByVal serializedObject As String) As T
        Dim serializer As XmlSerializer = New XmlSerializer(GetType(T))
        Using reader As StringReader = New StringReader(serializedObject)
            Return CType(serializer.Deserialize(reader), T)
        End Using
    End Function
End Class
然后,当您加载数据时,您可以简单地执行以下操作:

Public Class DrawerSystem
    Public ID As String
    Public Name As String
    Public Location As String
End Class
Private Sub AddNode(drawerSystem As DrawerSystem)
    Dim node As TreeNode = TreeView1.Nodes.Add(drawerSystem.Name)
    node.Tag = drawerSystem
End Sub
Dim drawerSystem As DrawerSystem = CType(e.Node.Tag, DrawerSystem)
Label1.Text = drawerSystem.ID
Label2.Text = drawerSystem.Location
Public Class My_LEGO_Elements
    Private Sub My_LEGO_Elements_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim serializer As New SimpleXmlSerializer()
        Dim data As LegoElementsData = serializer.DeSerialize(Of LegoElementsData)(File.ReadAllText("C:\Users\Steven\Documents\Visual Studio 2012\Projects\My_LEGO_Elements\My_LEGO_Elements\Drawer_Systems_3.xml"))
        ListBox1.Items.AddRange(data.DrawerSystems.ToArray())
    End Sub

    Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedValueChanged
        Dim drawerSystem As DrawerSystem = CType(ListBox1.SelectedItem, DrawerSystem)
        Label1.Text = drawerSystem.Id
        Label2.Text = drawerSystem.Location
        Label3.Text = drawerSystem.Name
        ListBox2.Items.Clear()
        ListBox2.Items.AddRange(drawerSystem.Drawers.ToArray())
    End Sub
End Class

谢谢你的回答。然而,这似乎对我不起作用。(Visual Studio 2012 RC显示SelectNode方法的错误。)我如何读取TreeNode.Tag属性?@user1517987我更新了我的答案,以修复我的错误并更清楚地解释标记的含义。感谢提供新信息,但我不确定在代码中的位置或如何放置它。我只是把我的代码添加到我的问题中以供参考。我按照建议重新构造了XML文件。我得到了正确显示抽屉系统的信息。在选择抽屉系统时,是否有办法在第二个列表框(或其他类型的控件)中显示有关各个抽屉的信息?另外,由于某些原因,我的图像不会显示在图片盒中。当然可以。我更新了我的答案,以展示一种方法的示例。另一件您可能想做的事是考虑使用DATAGRID控件或ListView控件(SET到Debug视图),这样您就可以在列表中显示每个项目的多个列。图像以什么方式不起作用?它会引发异常吗?如果是,有什么信息?