【问题标题】:Reading XML data using LINQ, multiple elements with the same name VB使用LINQ读取XML数据,多个同名元素VB
【发布时间】:2017-10-28 01:19:29
【问题描述】:

我有一个包含多个同名节点的 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

这可行,但只返回第一个分支,请帮助,我是一个完整的新手!

【问题讨论】:

    标签: xml vb.net visual-studio linq


    【解决方案1】:

    您的问题是您使用方法 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
    

    【讨论】:

    • 您好,谢谢您,但是我在 ComboBox2.Items.AddRange(branches) 行上遇到错误,错误是 System.InvalidCastException: 'Unable to cast object of type 'WhereSelectEnumerableIterator`2[System. Xml.Linq.XElement,System.String]' 输入'System.Object[]'。'
    【解决方案2】:

    尝试以下:

       Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim xdoc As XDocument = XDocument.Load(FILENAME)
            Dim versions As IEnumerable(Of XElement) = xdoc.Descendants("Version")
            For Each version As XElement In versions
                For Each trunk As XElement In version.Elements("Trunk")
                    Console.WriteLine(CType(trunk, String))
                    ComboBox1.Items.Add(CType(trunk, String))
                Next trunk
    
                For Each xEle As XElement In version.Elements("Branch")
                    Console.WriteLine(CType(xEle, String))
                    ComboBox2.Items.Add(CType(xEle, String))
                Next xEle
            Next version
    
        End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多