Я получаю xml от третьей стороны, и мне нужно десериализовать его на объект С#. Этот xml может содержать атрибуты со значением целочисленного типа или пустым значением: attr = "11" или attr = ". Я хочу десериализовать это значение атрибута в свойстве с типом целочисленного целочисленного значения. Но XmlSerializer не поддерживает десериализацию в типы с нулевым значением. Следующий тестовый код выходит из строя во время создания XmlSerializer с InvalidOperationException {" Произошла ошибка, отражающая тип "TestConsoleApplication.SerializeMe".}.
[XmlRoot("root")]
public class SerializeMe
{
[XmlElement("element")]
public Element Element { get; set; }
}
public class Element
{
[XmlAttribute("attr")]
public int? Value { get; set; }
}
class Program {
static void Main(string[] args) {
string xml = "<root><element attr=''>valE</element></root>";
var deserializer = new XmlSerializer(typeof(SerializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (SerializeMe)deserializer.Deserialize(xmlStream);
}
}
Когда я меняю тип свойства "Значение" на int, десериализация не выполняется с InvalidOperationException:
В документе XML есть ошибка (1, 16).
Может кто-нибудь посоветует, как десериализовать атрибут с пустым значением в nullable type (как null), в то же время десериализуя непустое значение атрибута в целое число? Есть ли какой-либо трюк для этого, поэтому мне не придется делать десериализацию каждого поля вручную (на самом деле их много)?
Обновление после комментария от ahsteele:
-
Насколько я знаю, этот атрибут работает только с XmlElementAttribute - этот атрибут указывает, что элемент не имеет содержимого, будь то дочерние элементы или основной текст. Но мне нужно найти решение для XmlAttributeAttribute. В любом случае я не могу изменить xml, потому что я не могу контролировать его.
-
Это свойство работает только тогда, когда значение атрибута не пусто или когда атрибут отсутствует. Когда attr имеет пустое значение (attr = ''), конструктор XmlSerializer терпит неудачу (как и ожидалось).
public class Element { [XmlAttribute("attr")] public int Value { get; set; } [XmlIgnore] public bool ValueSpecified; }
-
Пользовательский класс Nullable, как в этом блоге Alex Scordellis
Я попытался перенять класс из этого сообщения в блоге в свою проблему:
[XmlAttribute("attr")] public NullableInt Value { get; set; }
Но конструктор XmlSerializer не работает с InvalidOperationException:
Невозможно выполнить сериализацию элемента "Значение" типа TestConsoleApplication.NullableInt.
XmlAttribute/XmlText не может использоваться для кодирования типов, реализующих IXmlSerializable}
-
Уродливое суррогатное решение (стыдно за меня, что я написал этот код здесь:)):
public class Element { [XmlAttribute("attr")] public string SetValue { get; set; } public int? GetValue() { if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 ) return null; int result; if (int.TryParse(SetValue, out result)) return result; return null; } }
Но я не хочу придумывать решение, подобное этому, потому что он нарушает интерфейс моего класса для его потребителей. Я бы лучше вручную реализовал интерфейс IXmlSerializable.
В настоящее время похоже, что я должен реализовать IXmlSerializable для всего класса Element (он большой), и нет простого обходного пути...