Частичная десериализация XML в объект
-
20-09-2019 - |
Вопрос
У меня есть некоторый XML-файл, который я десериализую в бизнес-объект.Я использую XmlSerializer.Для этого выполните десериализацию.Однако я хочу, чтобы один из XmlElement, содержащихся в XML, оставался XElement.
Это не может быть сделано напрямую (с использованием атрибута XmlElementAttribute), поскольку XElement не является сериализуемым.Я также попытался сериализовать этот элемент в строку (в двухэтапной попытке получить XElement), но это не удалось с ошибкой:
элемент неожиданного типа узла.метод readelementstring может быть вызван только для элементов с простым или пустым содержимым
Есть какие-нибудь идеи, как это можно сделать?
Вот пример xml и результирующего объекта, который я хочу:
<Person name="Joe">
<Hobbies>
<Hobby name="Reading" .../>
<Hobby name="Photography" .../>
</Hobbies>
<HomeAddress>
...
</HomeAddress>
</Person>
Объект:
public class Person
{
[XmlAttribute("Name")]
public string Name {get; set;}
?????
public XElement Hobbies {get; set;}
[XmlElement("HomeAddress")]
public Address HomeAddress {get; set;}
}
Попытки, которые не срабатывают:
[XmlElement("Hobbies")]
public XElement Hobbies {get; set;}
[XmlElement("Hobbies")]
public string Hobbies {get; set;}
Решение
Чтобы избежать тяжелой работы по внедрению чего-то вроде IXmlSerializable
, вы могли бы сделать что-то вроде полускрытого сквозного XmlElement
собственность;однако обратите внимание, что это не совсем то, что вы хотите, поскольку у вас может быть только один root XElement
значение (не два, как в вашем примере);для этого вам понадобится список...
using System;
using System.ComponentModel;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
public class Person
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlIgnore]
public XElement Hobbies { get; set; }
[XmlElement("Hobbies")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public XmlElement HobbiesSerialized
{
get
{
XElement hobbies = Hobbies;
if(hobbies == null) return null;
XmlDocument doc = new XmlDocument();
doc.LoadXml(hobbies.ToString());
return doc.DocumentElement;
}
set
{
Hobbies = value == null ? null
: XElement.Parse(value.OuterXml);
}
}
[XmlElement("HomeAddress")]
public Address HomeAddress { get; set; }
}
public class Address { }
static class Progmam
{
static void Main()
{
var p = new Person { Hobbies = new XElement("xml", new XAttribute("hi","there")) };
var ser = new XmlSerializer(p.GetType());
ser.Serialize(Console.Out, p);
}
}
Другие советы
Чтобы иметь полный контроль (наряду с полной ответственностью) за то, как генерируется XML, вы можете заставить свой класс реализовать System.Xml.Serialization.Интерфейс IXmlSerializable и переопределить ReadXml и WriteXml.Мне приходилось делать это раньше со словарными классами - обязательно тщательно протестируйте, особенно с нулевыми свойствами, пустыми полями и т.д.