Сериализация XML в .NET — что с этим не так

#c# #vb.net #xml-serialization

#c# #vb.net #xml-сериализация

Вопрос:

У меня такой xml:

 <?xml version="1.0" encoding="utf-8"?>
<session xmlns="http://winscp.net/schema/session/1.0" name="blah@blah.com" start="2011-10-03T15:09:30.481Z">
  <ls>
    <destination value="/incoming/monthly" />
    <files>
      <file>
        <filename value="2.txt" />
        <type value="D" />
        <modification value="2011-09-14T12:58:26.000Z" />
        <permissions value="rwxr-xr-x" />
      </file>
      <file>
        <filename value="3.txt" />
        <type value="D" />
        <modification value="2011-01-03T22:04:55.000Z" />
        <permissions value="rwxr-xr-x" />
      </file>
    </files>
    <result success="true" />
  </ls>
</session>
  

Мое представление следующего:

   <XmlRoot("session", Namespace:="http://winscp.net/schema/session/1.0")>
    Class XMLSession
        <XmlElement("ls/files/file")>
        Public Property FileList As New List(Of XMLFile)
    End Class

 <XmlType("file")>
    Class XMLFile
        <XmlElement("filename")>
        Public Property FileName As XMLValueAttribute
        <XmlElement("type")>
        Public Property TypeName As XMLValueAttribute
        <XmlElement("permissions")>
        Public Property Permissions As XMLValueAttribute
        <XmlElement("modification")>
        Public Property ModificationDate As XMLValueAttribute
    End Class

  Class XMLValueAttribute
        <XmlAttribute("value")>
        Public Property Value As String
    End Class
  

Почему XMLSession.Список файлов.Считайте всегда 0. Я предполагаю, что это как-то связано с объявлением над ним, но я не уверен, что с этим не так. Возможно, он не может принять путь, если нет, как я могу это сделать?

Комментарии:

1. Исправлен ли ваш формат XML? Похоже, это может потребовать некоторой работы. Например, вместо <file><filename value="2.txt" /></file> , что-то вроде <file filename="2.txt" /> имело бы больше смысла — похоже, что все ваши подэлементы имеют только одно значение. Если бы вы внесли это изменение, ваша сериализация также была бы намного проще.

2. Этот формат генерируется WinSCP, поэтому я не могу его контролировать

Ответ №1:

Вы не можете описать несколько уровней XML с помощью одного атрибута XmlElementAttribute. Вам нужны классы для каждого уровня.

Комментарии:

1. Есть ли способ избежать наличия классов для каждого из них?

2. @marc_s: Ваш комментарий не совсем верен. Вам не нужен класс для «файлов», например, если вы используете <XMLArray(«files»)> . Теперь, если бы мне не нужен был класс для «Ls»

Ответ №2:

Если вы не хотите создавать классы вручную, вы можете получить инструменты, которые сделают это за вас:

Предполагая, что ваш XML сохранен в data.xml :

 xsd.exe data.xml
  

Это даст вам data.xsd определение XML.

 xsd.exe /l:VB /n:SomeNamespace /c data.xsd
  

Это даст вам кодовый data.vb файл с определенными вашими типами, который вы можете добавить в свой проект.

Проблема с этим заключается в том, что есть какая-то ошибка, описанная здесь, которая выдает ошибку при создании сериализатора вокруг этого нового типа. Итак, вам просто нужна одна ручная настройка сгенерированного кода, изменение:

 <XmlArrayItemAttribute("file", GetType(sessionLSFilesFile), IsNullable:=False)> _
'To
<XmlArrayItemAttribute("file", GetType(sessionLSFilesFile()), IsNullable:=False)> _
  

Комментарии:

1. жаль, что я не знал об этом до того, как начал 😉 Спасибо

2. @Denis: все это есть в документации.