0

サンプル 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 ノードの値を同時に取得するにはどうすればよいですか?

TreeView コントロールに XML ファイルを設定しました。コントロールで選択したノードとサブノードの間の特定の値を (文字列として) 取得したいと考えています。

私の期待される結果

Drawer_System_1 ノードまたは任意のサブノードを選択した場合、DrawerSystemID、DrawerSysName、および DrawerSysLocation ノード間の値を取得したいと考えています。

Drawers ノードまたは任意のサブノードを選択した場合、前述の値を保持し、DrawerID および Contents ノードの値も取得したいと考えています。

各ノードの値は個別のラベルに表示する必要がありますが、要求したデータを複数行のテキスト ボックス (またはラベル) に表示する方が簡単であれば、それも問題ありません。

ノート

私は VB.NET を使用していますが、C# で解決策を思いつくことができれば、それも問題ありません。オンライン コンバーターを使用して、答えを VB に変換できるはずです。

必要に応じて、プログラムが読みやすいように XML ファイルを再構築できます。

編集:これまでの私のコードは次のとおりです:

Imports System
Imports System.Xml
Imports System.Xml.Serialization
Imports System.IO

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_5.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)
        DrawerSysIDLabel.Text = drawerSystem.Id
        DrawerSysNameLabel.Text = drawerSystem.Name
        DrawerSysLocLabel.Text = drawerSystem.Location
        'retrieve specific drawer system image from resources
        Dim pictureResource = My.Resources.ResourceManager.GetObject(String.Format("{0}", drawerSystem.Id))
        'convert pictureResource to type Image and display in DrawerSysPictureBox
        DrawerSysPictureBox.Image = CType(pictureResource, Image)
    End Sub 'My_LEGO_Elements_Load

    Private Sub ListBox2_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox2.SelectedValueChanged
        Dim drawer As Drawer = CType(ListBox2.SelectedItem, Drawer)
        DrawerNumberLabel.Text = drawer.Id
        DrawerContentsLabel.Text = drawer.Contents
    End Sub
End Class 'My_LEGO_Elements

Public Class LEGOElementsData
    Public Property DrawerSystems() As List(Of DrawerSystem)
        Get
            Return _drawerSystems
        End Get
        Set(ByVal value As List(Of DrawerSystem))
            _drawerSystems = value
        End Set
    End Property
    Private _drawerSystems As List(Of DrawerSystem)
End Class


Public Class DrawerSystem
    Public Property Id() As String
        Get
            Return _id
        End Get
        Set(ByVal value As String)
            _id = value
        End Set
    End Property
    Private _id As String

    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    Private _name As String

    Public Property Location() As String
        Get
            Return _location
        End Get
        Set(ByVal value As String)
            _location = value
        End Set
    End Property
    Private _location As String

    Public Property Drawers() As List(Of Drawer)
        Get
            Return _drawers
        End Get
        Set(ByVal value As List(Of Drawer))
            _drawers = value
        End Set
    End Property
    Private _drawers As List(Of Drawer)

    Public Overrides Function ToString() As String
        Return _name
    End Function
End Class


Public Class Drawer
    Public Property Id() As String
        Get
            Return _id
        End Get
        Set(ByVal value As String)
            _id = value
        End Set
    End Property
    Private _id As String

    Public Property Contents() As String
        Get
            Return _contents
        End Get
        Set(ByVal value As String)
            _contents = value
        End Set
    End Property
    Private _contents As String
End Class

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

提案どおりに XML ファイルを再構築しました。ドロワー システムの情報が正しく表示されるようになりました。引き出しシステムを選択したときに、2 番目の ListBox (または別の種類のコントロール) に個々の引き出しに関する情報を表示する方法はありますか? また、何らかの理由で画像が PictureBox に表示されません。

4

1 に答える 1

0

それを行う奇妙な方法のように聞こえます。XMLをTreeViewコントロールにロードしている場合、必要なすべてのデータをTreeNode.Tagプロパティに格納するか、TreeViewの外部のメモリ内のデータ構造に格納することになるので、ノードを選択すると、子要素のデータを取得するために XML に戻る必要はありません。ただし、そうしたい場合は、XML からそのデータを読み取る 1 つの方法を次に示します。

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.Tag単なるプロパティです。Object文字列、リスト、データ セット、独自のカスタム オブジェクト、またはその他のものと等しく設定できます。あなたにとって意味のあるものは何でも、それがその目的です。ツリー内の各ノードに関するカスタム データを保存して、後で (ノードが選択されたときなどに) アクセスできるようにすることができます。たとえば、次のような独自のクラスがあるとします。

Public Class DrawerSystem
    Public ID As String
    Public Name As String
    Public Location As String
End Class

次に、引き出しシステムの「TreeNode」を作成するときに、次のようにタグを設定できます。

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

XML のすべての要素を TreeView の同じ階層に表示する必要がある理由を正確に理解できません。引き出しシステムの単純なリストで十分であるように思えます。次に、リスト内の項目が選択されると、その引き出しシステムに関するすべての詳細を他のコントロールに表示できます。また、XML をループ処理するのではなく、XML を逆シリアル化して一致するデータ構造にすることをお勧めします。たとえば、XML を次のように再フォーマットした場合 (デシリアライズしやすくするため):

<LegoElementsData>
  <DrawerSystems>
    <DrawerSystem>
      <Id>1</Id>
      <Name>Drawer_System_1</Name>
      <Location>North Wall (2nd from left)</Location>
      <Drawers>
        <Drawer>
          <Id>1-01</Id>
          <Contents>Contents of Drawer 1-01</Contents>
        </Drawer>
        <Drawer>
          <Id>1-02</Id>
          <Contents>Contents of Drawer 1-02</Contents>
        </Drawer>
      </Drawers>
    </DrawerSystem>
  </DrawerSystems>
</LegoElementsData>

次に、次のように、コード内で一致するデータ構造を作成できます。

Public Class LegoElementsData
    Public Property DrawerSystems() As List(Of DrawerSystem)
        Get
            Return _drawerSystems
        End Get
        Set(ByVal value As List(Of DrawerSystem))
            _drawerSystems = value
        End Set
    End Property
    Private _drawerSystems As List(Of DrawerSystem)
End Class


Public Class DrawerSystem
    Public Property Id() As String
        Get
            Return _id
        End Get
        Set(ByVal value As String)
            _id = value
        End Set
    End Property
    Private _id As String

    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    Private _name As String

    Public Property Location() As String
        Get
            Return _location
        End Get
        Set(ByVal value As String)
            _location = value
        End Set
    End Property
    Private _location As String

    Public Property Drawers() As List(Of Drawer)
        Get
            Return _drawers
        End Get
        Set(ByVal value As List(Of Drawer))
            _drawers = value
        End Set
    End Property
    Private _drawers As List(Of Drawer)

    Public Overrides Function ToString() As String
        Return _name
    End Function
End Class


Public Class Drawer
    Public Property Id() As String
        Get
            Return _id
        End Get
        Set(ByVal value As String)
            _id = value
        End Set
    End Property
    Private _id As String

    Public Property Contents() As String
        Get
            Return _contents
        End Get
        Set(ByVal value As String)
            _contents = value
        End Set
    End Property
    Private _contents As String

    Public Overrides Function ToString() As String
        Return _id & " - " & _ contents
    End Function
End Class

次に、あなたの人生を楽にするために、次のようなプロセスを少し簡素化する独自のシリアライザー クラスを作成することをお勧めします。

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 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
于 2012-07-12T12:11:15.440 に答える