Может ли XmlSerializer десериализоваться в Nullable ‹int›?

Я хотел десериализовать XML-сообщение, содержащее элемент, который можно пометить nil="true", в класс со свойством типа int?. Единственный способ заставить его работать - это написать свой собственный NullableInt тип, реализующий IXmlSerializable. Есть ли способ лучше?

Я написал полную проблему и способ ее решения в моем блоге.


person Alex Scordellis    schedule 20.11.2008    source источник


Ответы (3)


Я думаю, вам нужно поставить перед nil = "true" префикс пространства имен, чтобы XmlSerializer десериализовался до нуля.

MSDN на xsi: nil

<?xml version="1.0" encoding="UTF-8"?>
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="array">
  <entity>
    <id xsi:type="integer">1</id>
    <name>Foo</name>
    <parent-id xsi:type="integer" xsi:nil="true"/>
person Phil Jenkins    schedule 20.11.2008
comment
Спасибо, Фил, это сработало. Теперь мне просто нужно, чтобы парень, предоставляющий сообщения, добавил пространство имен ... - person Alex Scordellis; 21.11.2008
comment
Не беспокойтесь, SCOA :-P Если вы не можете изменить XML в источнике (хотя звучит так, как будто можете), вы можете передать его через преобразование XSLT, чтобы добавить пространство имен, я думаю ... - person Phil Jenkins; 21.11.2008
comment
Да, JENP, оказывается сложно сделать это в исходном коде, поскольку это приложение Rails, создающее xml с to_xml. Кроме того, добавление xsi: к атрибуту type заставляет .NET искать тип с именем array, которого не существует. Так что, в конце концов, будет легче придерживаться моего типа NullableInt. - person Alex Scordellis; 21.11.2008
comment
У меня точно такая же проблема, я не могу изменить api и, вероятно, собираюсь пойти по маршруту XSLT (хотя я не очень далеко ухожу с этим) - person ChadT; 22.06.2010

Мое решение - предварительно обработать узлы, исправив любые атрибуты "nil":

public static void FixNilAttributeName(this XmlNode @this)
{
    XmlAttribute nilAttribute = @this.Attributes["nil"];
    if (nilAttribute == null)
    {
        return;
    }

    XmlAttribute newNil = @this.OwnerDocument.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance");
    newNil.Value = nilAttribute.Value;
    @this.Attributes.Remove(nilAttribute);
    @this.Attributes.Append(newNil);
}

Я объединяю это с рекурсивным поиском дочерних узлов, чтобы для любого заданного XmlNode (или XmlDocument) я мог выполнить один вызов перед десериализацией. Если вы хотите сохранить исходную структуру в памяти неизменной, работайте с Clone () XmlNode.

person Tom Mayfield    schedule 16.10.2009
comment
Мне это очень понравилось, спасибо. И явно для потребления Rails. Я сделал небольшую корректировку, чтобы проверить ненулевые атрибуты: XmlAttribute nilAttribute = null; если (@ this.Attributes! = null) {nilAttribute = @ this.Attributes [ноль]; } - person Dylan; 20.02.2011

Исключительно ленивый способ сделать это. Он хрупкий по ряду причин, но мой XML достаточно прост, чтобы гарантировать такое быстрое и грязное исправление.

xmlStr = Regex.Replace(xmlStr, "nil=\"true\"", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\"");
person sipsorcery    schedule 29.01.2011