Используйте XmlReader для получения имени и значения из XML-файла в VB.NET - PullRequest
0 голосов
/ 28 июня 2018

Я использую следующий XML-файл и код VB. Я хочу иметь возможность получить имя проекта, которое находится в теге проекта, а также значение того, что находится между тегами. Получение значения «Имя» работает нормально, но я не могу понять, как читать какие-либо из подпунктов. Я хочу заполнить 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 это "описание". Я не понимаю как.

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()

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Вы можете заставить VS создать класс, соответствующий XML-файлу, а затем вы можете использовать этот класс для получения данных, иногда очень просто.

Я поместил DataGridView в форму и использовал этот код:

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

Чтобы получить это:

enter image description here

При необходимости измените имена классов и свойств.

Конечно, вам нужен класс для работы с XML-файлом. Для этого скопируйте данные XML, а затем в Visual Studio выберите «Редактировать» -> «Специальная вставка» -> «Вставить XML как классы». Я решил вставить его в класс с именем «Проекты» и получил следующее:

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" ?>.

0 голосов
/ 28 июня 2018

Я написал этот код для вашего XML, чтобы получить имя файла (проект / имя) и заголовок (описание). Я надеюсь, что вы можете понять это:)

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>. Вам нужно использовать .ReadElementString, если вы хотите получить элемент между тегами <>element<>.

...