使用 XmlReader 从 VB.NET 中的 XML 文件获取名称和值

Use XmlReader to get a name and value from an XML File in VB.NET

我正在使用以下 XML 文件和 VB 代码。我希望能够获取项目标签中的项目名称以及标签之间的任何值。获取 "Name" 值工作正常,但我似乎无法弄清楚如何读取任何子项。我想用 2 列数据填充 ListView 或者可能是 DataGrid:

project   |  description
------------------------
file001   |  ABC Project
file002   |  DEF Project

XML 文件:

<?xml version="1.0"?>
<menu>
    <header>
        <listname>Files list</listname>
        <lastlistupdate>02/08/2018</lastlistupdate>
    </header>
    <project name="file001" index="true" image="'">
        <description>ABC Project</description>
        <month>January</month>
    </project>
    <project name="file002" index="true" image="'">
        <description>DEF Project</description>
        <month>February</month>
    </project>
        <project name="file003" index="true" image="'">
        <description>Not really important project</description>
        <month>March</month>
    </project>
</menu>

此代码的奇怪之处在于 "IF" 测试通过,这意味着 xr.Name 必须是 "project"。但是,我的日志测试行 (xr.Name.ToString) 显示 .Name 是 "description"。没看懂。

Dim xmlfile As String = ""
Dim filename As String = ""
Dim title As String = ""
ListViewFiles.Items.Clear()
xmlfile = Application.StartupPath & "\projectlist.xml"

Dim xr As XmlReader = XmlReader.Create(xmlfile)
While xr.Read()
    If xr.NodeType = XmlNodeType.Element AndAlso xr.Name = "project" Then
        filename = xr.GetAttribute(0) 'Gets "name" correctly (ex: file001)
        title = Trim(xr.ReadString()) '<<<<-- will not work
        WriteLog("xr.name: " & xr.Name.ToString) <-shows the tag "description"???
        ListViewFiles.Items.Add(New ListViewItem(New String() {filename, title}))
    End If
End While
xr.Close()

我为您的 XML 编写了这段代码,以获取文件名 (project/name) 和标题(说明)。希望你能看懂:)

Dim filename As String = ""
Dim title As String = ""
Dim XMLReader As XmlReader = XMLReader.Create(xmlfile)
With XMLReader
    'As long as the reader hasnt come to the end of the document, this loop is executed'
    Do While .Read
    If .IsStartElement() Then
        Select Case .Name
        Case "project"
            filename = .GetAttribute(0)
            Console.WriteLine(filename)
        Case "description"
            title = .ReadElementString
            Console.WriteLine(title)
            Console.WriteLine("Found: " & filename & " - " & title) 
            'you can place your "final" code here.'
            Exit Select
        Case Else
            .Read()
            'continue reading if nothing is special'
        End Select
    End If
    Loop
    .Close() 'close the reader. All done!'
End With

您可以在此处测试代码:https://dotnetfiddle.net/3CDd6Q

在您的原始代码中存在一些错误,例如您使用 xr.Name 来获取描述标签的元素,但是使用 .Name 您只能获取 <name> 标签的名称。如果要获取 <>element<> 标签之间的元素,则需要使用 .ReadElementString

你可以让VS做一个class对应XML文件,然后你就可以用那个class来获取数据,有时候很简单。

我将 DataGridView 放在 Form 上并使用了以下代码:

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

Public Class Form1

    Class Project
        Property Filename As String
        Property Description As String
    End Class

    Private Sub LoadData()
        Dim xmlFile = "C:\temp\projectlist.xml"
        Dim projectsData As Projects.menu

        Dim serializer = New XmlSerializer(GetType(Projects.menu))
        Using fs As New FileStream(xmlFile, FileMode.Open, FileAccess.Read, FileShare.Read)
            Using rdr = XmlReader.Create(fs)
                projectsData = DirectCast(serializer.Deserialize(rdr), Projects.menu)
            End Using
        End Using

        Dim projectsList = projectsData.project.Select(Function(p) New Project With {.Filename = p.name, .Description = p.description}).ToList()

        DataGridView1.DataSource = projectsList

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        LoadData()
        DataGridView1.AutoResizeColumn(0)
        DataGridView1.AutoResizeColumn(1)

    End Sub

End Class

得到这个:

请根据需要调整 classes 和属性的名称。

当然,您需要 class 来配合 XML 文件。为此,复制 XML 数据,然后在 Visual Studio 中选择 "Edit"->"Paste Special"->"Paste XML as classes"。我选择将它粘贴到一个名为 "Projects" 的 class 中并得到了这个:

Public Class Projects

    <System.SerializableAttribute(),
 System.ComponentModel.DesignerCategoryAttribute("code"),
 System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True),
 System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)>
    Partial Public Class menu

        Private headerField As menuHeader

        Private projectField() As menuProject

        '''<remarks/>
        Public Property header() As menuHeader
            Get
                Return Me.headerField
            End Get
            Set
                Me.headerField = Value
            End Set
        End Property

        '''<remarks/>
        <System.Xml.Serialization.XmlElementAttribute("project")>
        Public Property project() As menuProject()
            Get
                Return Me.projectField
            End Get
            Set
                Me.projectField = Value
            End Set
        End Property
    End Class

    '''<remarks/>
    <System.SerializableAttribute(),
System.ComponentModel.DesignerCategoryAttribute("code"),
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
    Partial Public Class menuHeader

        Private listnameField As String

        Private lastlistupdateField As String

        '''<remarks/>
        Public Property listname() As String
            Get
                Return Me.listnameField
            End Get
            Set
                Me.listnameField = Value
            End Set
        End Property

        '''<remarks/>
        Public Property lastlistupdate() As String
            Get
                Return Me.lastlistupdateField
            End Get
            Set
                Me.lastlistupdateField = Value
            End Set
        End Property
    End Class

    '''<remarks/>
    <System.SerializableAttribute(),
System.ComponentModel.DesignerCategoryAttribute("code"),
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)>
    Partial Public Class menuProject

        Private descriptionField As String

        Private monthField As String

        Private nameField As String

        Private indexField As Boolean

        Private imageField As String

        '''<remarks/>
        Public Property description() As String
            Get
                Return Me.descriptionField
            End Get
            Set
                Me.descriptionField = Value
            End Set
        End Property

        '''<remarks/>
        Public Property month() As String
            Get
                Return Me.monthField
            End Get
            Set
                Me.monthField = Value
            End Set
        End Property

        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()>
        Public Property name() As String
            Get
                Return Me.nameField
            End Get
            Set
                Me.nameField = Value
            End Set
        End Property

        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()>
        Public Property index() As Boolean
            Get
                Return Me.indexField
            End Get
            Set
                Me.indexField = Value
            End Set
        End Property

        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()>
        Public Property image() As String
            Get
                Return Me.imageField
            End Get
            Set
                Me.imageField = Value
            End Set
        End Property
    End Class


End Class

P.S。我将编码放在 XML 文件的声明中:<?xml version="1.0" encoding="utf-8" ?>.