XML Ошибка, «Данные на уровне root недопустимы» - PullRequest
1 голос
/ 24 апреля 2020

Я сохраняю список объектов как XML со следующим кодом в Windows Project Project.

SaveFileDialog1.ShowDialog()
Dim Path = SaveFileDialog1.FileName
Dim file As StreamWriter
System.IO.File.WriteAllText(Path, "")
file = My.Computer.FileSystem.OpenTextFileWriter(Path, False)
Dim ser As New XmlSerializer(GetType(List(Of Player)))
ser.Serialize(file, PlayerList)
file.WriteLine(ser)
file.Close()

И чтение его обратно с помощью:

OpenFileDialog1.ShowDialog()
Dim Path = OpenFileDialog1.FileName
Dim reader As New System.Xml.Serialization.XmlSerializer(GetType(List(Of Player)))
Dim filereader As New System.IO.StreamReader(Path)
PlayerList = reader.Deserialize(filereader)

Файл выглядит правильно, вот что получается, когда у меня в списке два объекта:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfPlayer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Player>
    <Name>Kennedy Igboananike</Name>
    <Control>999</Control>
    <Tackling>999</Tackling>
    <Passing>999</Passing>
    <Heading>999</Heading>
    <Shooting>1000</Shooting>
    <Speed>731</Speed>
    <Age>30</Age>
  </Player>
  <Player>
    <Name>Dean Wormall</Name>
    <Control>408</Control>
    <Tackling>390</Tackling>
    <Passing>579</Passing>
    <Heading>428</Heading>
    <Shooting>449</Shooting>
    <Speed>719</Speed>
    <Age>17</Age>
  </Player>
</ArrayOfPlayer>System.Xml.Serialization.XmlSerializer

Но при попытке прочитать его обратно я получаю сообщение об ошибке:

Данные на уровне root недопустимы. Строка X, позиция 17

, что соответствует сразу после /ArrayOfPlayer и началу System.Xml ... et c.

Из того, что я могу сказать, глядя на другие примеры xml, окончательный System.Xml.Serialization.XmlSerializer не должен быть там и, похоже, вызывает проблему, но я не могу понять из своего кода, почему это присоединяется в конце. Я пытаюсь это с совершенно пустыми файлами, так что это ничего из предыдущей записи.

Код взят из разных мест, так что это немного ми sh -ma sh, так как я пытался решить, как сериализовать / десериализовать список объектов.

Мой класс находится в отдельном файле и выглядит так:

<Serializable>
Public Class Player
    Public Property Name As String
    Public Property Control As Integer
    Public Property Tackling As Integer
    Public Property Passing As Integer
    Public Property Heading As Integer
    Public Property Shooting As Integer
    Public Property Speed As Integer
    Public Property Age As Integer

End Class

1 Ответ

1 голос
/ 24 апреля 2020

Вам не нужно:

System.IO.File.WriteAllText(Path, "")
My.Computer.FileSystem.OpenTextFileWriter(Path, False)
  • Если вы хотите перезаписать существующие данные, достаточно указать false в качестве аргумента добавления.
  • Вам не нужно OpenTextFileWriter, вы можете просто передать выбранный путь к файлу конструктору StreamReader.

Ошибка:

file.WriteLine(ser)

Записывает тип ser (System.Xml.Serialization.XmlSerializer) в конец файла. Вы этого не хотите.

Здесь я объявляю новый SaveFileDialog() (я не использую компонент SaveFileDialog, просто объект класса - вам не нужен компонент пользовательского интерфейса для открытия диалога) с Using, поэтому он будет удален сразу после завершения кода в блоке Using.
То же самое относится к StreamWriter: когда его текущие операции завершатся, он будет удален и поток flush:

Using sfd As New SaveFileDialog()
    sfd.Filter = "XML Files|*.xml"
    sfd.RestoreDirectory = True
    If sfd.ShowDialog() = DialogResult.OK Then
        Using writer As New StreamWriter(sfd.FileName, False)
            Dim ser As New XmlSerializer(GetType(List(Of Player)))
            ser.Serialize(writer, PlayerList)
        End Using
    End If
End Using

Чтобы прочитать его обратно, выполните обратное:
DirectCast используется, потому что XmlSerializer.Deserialize возвращает тип объекта.

Dim PlayerList As New List(Of Player)
Using ofd As New OpenFileDialog()
    ofd.Filter = "XML Files|*.xml"
    ofd.RestoreDirectory = True
    If ofd.ShowDialog() = DialogResult.OK Then
        Dim serializer As New XmlSerializer(GetType(List(Of Player)))
        Using reader As New StreamReader(ofd.FileName)
            PlayerList = DirectCast(serializer.Deserialize(reader), List(Of Player))
        End Using
    End If
End Using
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...