Obtengo un xml del tercero y necesito deserializarlo en el objeto C#. Este xml puede contener atributos con valor de tipo entero o valor vacío: attr = "11" o attr = "". Quiero deserializar este valor de atributo en la propiedad con el tipo de entero nullable. Pero XmlSerializer no admite la deserialización en tipos anulables. El siguiente código de prueba falla durante la creación de XmlSerializer con InvalidOperationException {"Hubo un error que refleja el tipo 'TestConsoleApplication.SerializeMe'."}.Deserializar el valor del atributo xml vacío en la propiedad int nullable utilizando XmlSerializer
[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);
}
}
Cuando cambio el tipo de propiedad 'valor' a int, deserialización falla con InvalidOperationException:
Hay un error en el documento XML (1, 16).
Puede alguien aconsejar cómo deserializar atributo con valor vacío en tipo anulable (como null) al mismo tiempo deserializar valor de atributo no vacía en el número entero? ¿Hay algún truco para esto así que no tendré que hacer la deserialización de cada campo manualmente (de hecho hay muchos de ellos)?
Update después de comentario de ahsteele:
-
Por lo que yo sé, este atributo sólo funciona con XmlElementAttribute - este atributo especifica que el elemento no tiene contenido, si los elementos o el cuerpo del niño texto. Pero necesito encontrar la solución para XmlAttributeAttribute. De todos modos, no puedo cambiar xml porque no tengo control sobre él.
-
Esta propiedad sólo funciona cuando el valor del atributo no está vacío o cuando el atributo no se encuentra. Cuando attr tiene un valor vacío (attr = '') el constructor XmlSerializer falla (como se esperaba).
public class Element { [XmlAttribute("attr")] public int Value { get; set; } [XmlIgnore] public bool ValueSpecified; }
Custom Nullable class like in this blog post by Alex Scordellis
Me trataron de adoptar la clase de esta entrada del blog a mi problema:
[XmlAttribute("attr")] public NullableInt Value { get; set; }
Pero XmlSerializer constructor falla con InvalidOperationException:
No se puede serializar miembro 'Valor' de tipo TestConsoleApplication.NullableInt.
XmlAttribute/xmltext no puede ser utilizado para codificar los tipos de aplicación IXmlSerializable}
solución sustituta feo (que pena por mí que escribí este código aquí :)):
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; } }
Pero Don No quiero llegar a una solución como esta porque rompe la interfaz de mi clase para sus consumidores. Sería mejor implementar manualmente la interfaz IXmlSerializable.
Actualmente parece que tengo que poner en práctica IXmlSerializable para toda la clase de elemento (que es grande) y no hay solución simple ...
El "Uso de XmlSerializer para deserializar en un anulable" enlace está muerto . [Aquí hay una versión en caché de google] (http://webcache.googleusercontent.com/search?q=cache:vT5GiyOCWyIJ:www.rqna.net/qna/zzrzt-deserialise-missing-xml-attribute-to-nullable-type .html) – Anttu
@Anttu Cambié el enlace en la respuesta al archivo Wayback Machine del original * Usando XmlSerializer para deserializar en un Nullable *. –
ahsteele