2008-11-20 9 views
7

Quería deserializar un mensaje XML que contiene un elemento que se puede marcar nil="true" en una clase con una propiedad del tipo int?. La única forma en que podía hacer que funcionara era escribir mi propio tipo NullableInt que implementa IXmlSerializable. Hay una mejor manera de hacerlo?¿Puede XmlSerializer deserializar en un Nullable <int>?

Escribí el problema completo y la forma en que lo resolvió on my blog.

Respuesta

5

Creo que debe prefijar el nil = "verdadero" con un espacio de nombres para que XmlSerializer se deserialice a nulo.

MSDN on 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"/> 
+0

Gracias Phil, eso funcionó. Ahora solo necesito que el tipo que proporciona los mensajes agregue el espacio de nombres ... –

+0

Sin preocupaciones SCOA :-P Si no puede cambiar el XML en la fuente (aunque suena como puede), podría pasarlo a través de una transformada XSLT para agregar el espacio de nombres creo ... –

+0

Sí JENP, resulta que es complicado hacerlo en la fuente, ya que es una aplicación de Rails que produce el xml con 'to_xml'. Además, al agregar xsi: al atributo de tipo, .NET busca un tipo llamado 'array', que no existe. Así que al final será más fácil seguir con mi tipo 'NullableInt'. –

3

Mi solución es pre-procesar los nodos, la fijación de cualquier "nulo" atributos:

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); 
} 

que esta pareja con una búsqueda recursiva de nodos secundarios, de modo que para cualquier XmlNode dado (o XmlDocument), puedo emitir una sola llamada antes de la deserialización. Si desea mantener la estructura en memoria original sin modificaciones, trabaje con un Clon() de XmlNode.

+0

Eso funcionó muy bien para mí, gracias. Y explícitamente para el consumo de Rails. Hice un pequeño ajuste para verificar atributos no nulos: XmlAttribute nilAttribute = null; if (@ this.Attributes! = Null) { nilAttribute = @ this.Attributes ["nil"]; } – Dylan

0

La forma excepcionalmente perezosa de hacerlo. Es frágil por una serie de razones, pero mi XML es lo suficientemente simple como para garantizar una solución tan rápida y sucia.

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