Десериализационный массив XmlSerializer / список нескольких объектов в корне

Я пытаюсь десериализовать следующий вывод XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Foo>
   <Val>Data1</Val>
</Foo>
<Foo>
   <Val>Data2</Val>
</Foo>

(Это вывод с аппаратного устройства, и его нельзя изменить)

У меня есть тип XML, определенный как:

    [XmlType(AnonymousType=true, Namespace="")]
    public class Foo
    {
        public string Val { get; set; }
    }

Я попытался десериализовать этот массив, создав сериализатор как:

  var s = new XmlSerializer(typeof(Foo[]));
  //or
  var s = new XmlSerializer(typeof(List<Foo>);

Но каждый вызов s.Deserialize() вызывает исключение InvalidOperaitonException:

 System.InvalidOperationException: <Foo xmlns=''> was not expected.

Заметка

 var s = new XmlSerializer(typeof(Foo));
 // Only deseralizes the first Foo (Data1).

Спасибо за вашу помощь.

6 ответов

Решение

Я думаю, что проблема с вашим предоставленным XML.

Тестовое приложение говорит

List<Foo> list = new List<Foo> {new Foo {Val = "Data1"}, new Foo {Val = "Data2"}};
var s = new XmlSerializer(typeof(List<Foo>));
StringBuilder sb = new StringBuilder();
XmlWriter wr = XmlWriter.Create(sb);
s.Serialize(wr, list);

string ss = sb.ToString();

var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);

И XML должен быть

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfFoo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Foo>
        <Val>Data1</Val>
    </Foo>
    <Foo>
        <Val>Data2</Val>
    </Foo>
</ArrayOfFoo>

Если вы можете удалить начальную линию

<?xml version="1.0" encoding="ISO-8859-1"?>

И минимизировать строку в

string s = "<ArrayOfFoo><Foo>   <Val>Data1</Val></Foo><Foo>   <Val>Data2</Val></Foo></ArrayOfFoo>";
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(s);
List<Foo> list = (List<Foo>)s2.Deserialize(sr);

Это может сработать.

Это не действительно Xml. Должен быть основной корневой элемент, чтобы он работал правильно.

Это не правильный xml, поэтому вы не можете десериализовать его как действительный xml. Вам нужен какой-то взлом, чтобы сделать эту работу. я бы предложил вставить в начале xml и вставить в конце xml. затем вы можете десериализовать его, поскольку вы не можете внести это изменение на стороне XML, сделайте это в своем коде.

String ss; 
// lets assume this holds your xml data in string.
ss.append("</ArrayOfFoo>");
ss.replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "<?xml version=\"1.0\" encoding=\"utf-16\"?> <ArrayOfFoo>")

var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr); 

теперь это вернет вам правильный список.

Как говорят другие авторы, этот XML, который производит аппаратное устройство, не совместим с тем, как.NET сериализует / десериализует объект. Допустимый XML, а.NET требует допустимый XML, имеет корневой элемент.

Я предлагаю:

  • либо вы модифицируете полученный XML-код так, чтобы он соответствовал тому, как Astander представляет его фрагмент кода XML.
  • или вы пишете простой xml-анализатор для вашего файла, который десериализует файл так, как вам нужно

бр, марсель

Технически, то, что у вас есть, это не правильно сформированный XML-документ (который имеет ровно один корневой элемент), а скорее хорошо сформированный внешний анализируемый объект (который может иметь любое количество элементов, не содержащихся в других элементах, а также текст). не содержится ни в каких элементах). Следовательно, он должен анализировать, если ваш синтаксический анализатор XML имеет точку входа для анализа EPE, а не документов. Вы также можете создать тупиковый документ, который включает в себя ссылку на ваш EPE и анализирует этот документ.

Xstream для.Net может быть полезным API

Другие вопросы по тегам