问题描述
我有一个包含多个同名节点的 xml
<?xml version="1.0" encoding="UTF-8"?> <Versions> <Version> <Trunk>GapGun Software Version 7.1</Trunk> <Branch>.142</Branch> <Branch>.145</Branch> <Branch>.148</Branch> <Branch>.153</Branch> <Branch>.176</Branch> </Version> <Version> <Trunk>GapGun Software Version 7.2</Trunk> <Branch>.142</Branch> <Branch>.145</Branch> <Branch>.148</Branch> <Branch>.153</Branch> <Branch>.176</Branch> </Version> </Versions>
我需要在使用 Trunk 作为查询过滤时填充一个组合框到目前为止我有这个代码
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim Versions As IEnumerable(Of XElement) = xelement.Elements() For Each Version In Versions Console.WriteLine(Version.Element("Trunk").Value) ComboBox1.Items.Add(Version.Element("Trunk").Value) Next Version End Sub Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim name = From nm In xelement.Elements("Version") Where CStr(nm.Element("Trunk")) = ComboBox1.Text Select nm For Each xEle As XElement In name Console.WriteLine(xEle) ComboBox2.Items.Add(xEle.Element("Branch").Value) Next xEle End Sub End Class
这可行,但只返回第一个分支,请帮助,我是一个完整的新手!
推荐答案
您的问题是您使用方法 XElement.Element 将返回给定名称的一个(第一个)元素.
来自文档:获取第一个(按文档顺序)具有指定 XName 的子元素.
您需要更改代码以循环所有"分支"元素,您可以使用 ComboBox.Items.AddRange 方法添加所有元素
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) _ Handles ComboBox1.SelectedIndexChanged Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim name = From nm In xelement.Elements("Version") Where CStr(nm.Element("Trunk")) = ComboBox1.Text Select nm For Each xEle As XElement In name Dim branches = xEle.Elements("Branch").Select(Function(el) el.Value).ToArray() Console.WriteLine(xEle) ComboBox2.Items.AddRange(branches) Next End Sub
为了使代码更简单并仅加载文件 - 您可以引入包含所有必需数据的 Version 类.
然后您不需要搜索正确的主干,并且将使用已经存在的分支.
Public Class Version Public Property Trunk As String Public Property Branches As List(Of String) End Class Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim xelement As XElement = XElement.Load("F:\Test.xml") ' Create collection of versions Dim versions = _ xelement.Elements(). Select(Function(version) Return New Version With { .Trunk = version.Element("Trunk").Value .Branches = version.Elements("Branch"). Select(Function(el) el.Value) } End Function) ' Bind collection of versions to ComboBox ' Name of property which will be used as displayed text ComboBox1.DisplayMember = "Trunk" ComboBox1.DataSource = versions End Sub
然后当用户选择树干填充分支组合框会简单得多
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) _ Handles ComboBox1.SelectionChangeCommitted Dim comboBox = DirectCast(sender, ComboBox) Dim selectedVersion = DirectCast(comboBox.SelectedItem, Version) ComboBox2.DataSource = selectedVersion.Branches End Sub
问题描述
I have an xml with multiple nodes of the same name
<?xml version="1.0" encoding="UTF-8"?> <Versions> <Version> <Trunk>GapGun Software Version 7.1</Trunk> <Branch>.142</Branch> <Branch>.145</Branch> <Branch>.148</Branch> <Branch>.153</Branch> <Branch>.176</Branch> </Version> <Version> <Trunk>GapGun Software Version 7.2</Trunk> <Branch>.142</Branch> <Branch>.145</Branch> <Branch>.148</Branch> <Branch>.153</Branch> <Branch>.176</Branch> </Version> </Versions>
I need to populate a combo box when filtered using the Trunk as a query so far i have this code
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim Versions As IEnumerable(Of XElement) = xelement.Elements() For Each Version In Versions Console.WriteLine(Version.Element("Trunk").Value) ComboBox1.Items.Add(Version.Element("Trunk").Value) Next Version End Sub Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim name = From nm In xelement.Elements("Version") Where CStr(nm.Element("Trunk")) = ComboBox1.Text Select nm For Each xEle As XElement In name Console.WriteLine(xEle) ComboBox2.Items.Add(xEle.Element("Branch").Value) Next xEle End Sub End Class
This works but only returns the first branch please help, i am a complete novice!
推荐答案
Your problem is that you using method XElement.Element which will return one(first) element of given name.
From docs: Gets the first (in document order) child element with the specified XName.
You need change code to loop all "Branch" elements and you can add all of them by using ComboBox.Items.AddRange method
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) _ Handles ComboBox1.SelectedIndexChanged Dim xelement As XElement = XElement.Load("F:\Test.xml") Dim name = From nm In xelement.Elements("Version") Where CStr(nm.Element("Trunk")) = ComboBox1.Text Select nm For Each xEle As XElement In name Dim branches = xEle.Elements("Branch").Select(Function(el) el.Value).ToArray() Console.WriteLine(xEle) ComboBox2.Items.AddRange(branches) Next End Sub
To make code little bid simpler and load files only ones - you can introduce Version class which contains all required data.
Then you don't need to search for correct trunk and will use already existing branches.
Public Class Version Public Property Trunk As String Public Property Branches As List(Of String) End Class Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim xelement As XElement = XElement.Load("F:\Test.xml") ' Create collection of versions Dim versions = _ xelement.Elements(). Select(Function(version) Return New Version With { .Trunk = version.Element("Trunk").Value .Branches = version.Elements("Branch"). Select(Function(el) el.Value) } End Function) ' Bind collection of versions to ComboBox ' Name of property which will be used as displayed text ComboBox1.DisplayMember = "Trunk" ComboBox1.DataSource = versions End Sub
Then when user selects trunk populating branches combobox will be much simpler
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) _ Handles ComboBox1.SelectionChangeCommitted Dim comboBox = DirectCast(sender, ComboBox) Dim selectedVersion = DirectCast(comboBox.SelectedItem, Version) ComboBox2.DataSource = selectedVersion.Branches End Sub