2010-02-12 35 views
7

He agregado algunos tipos de valor que aceptan valores nulos a mi clase serializable. Realizo una serialización usando XmlSerializer pero cuando el valor se establece en null, obtengo un nodo vacío con xsi:nil="true". Este es el comportamiento correcto que he encontrado en Xsi:nil Attribute Binding Support.Prevenir <xsi: nil = "true"> en Tipos de valores anulables al serializar en XML

¿Hay alguna manera de desactivar esta opción para que no salga nada cuando el tipo de valor es null?

Respuesta

3

que he tenido el mismo problema .. aquí está uno de los lugares que leí sobre la manipulación de los tipos de valor anulables al serializar a XML: http://stackoverflow.com/questions/244953/serialize-a-nullable-int

mencionan acerca del uso de patrones incorporados como crear propiedades adicionales de valor anulable tipos. como por una propiedad denominada

public int? ABC 

debe agregar ya sea public bool ShouldSerializeABC() {return ABC.HasValue;} o público bool ABCSpecified { get { return ABC.HasValue; } }

sólo estaba serializar a XML para enviar a un proc almacenado de SQL, así que yo también ha evitado el cambio de mis clases. Estoy haciendo una comprobación [not(@xsi:nil)] en todos los elementos que aceptan nulos en mi consulta .value().

+0

simplemente me puse en un paso intermedio para escanear el código XML después de que fue serializada y eliminar cualquier 'xsi: nil = "true"' nodos. – Ryall

+0

roger eso. ¡Gracias! – Chin

3

Encontré que el bool público ABCSpecified era el único que funcionaba con .NET 4.0. También he tenido que añadir la XmlIgnoreAttribute

Aquí fue mi solución completa para suprimir una cadena denominado ABC en el archivo de referencia Web Resource.cs:

// backing fields 
private string abc; 
private bool abcSpecified; // Added this - for client code to control its serialization 

// serialization of properties 
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] 
public string ABC 
{ 
    get 
    { 
     return this.abc; 
    } 
    set 
    { 
     this.abc= value; 
    } 
} 

// Added this entire property procedure 
[System.Xml.Serialization.XmlIgnoreAttribute()] 
public bool ABCSpecified 
{ 
    get 
    { 
     return this.abcSpecified; 
    } 
    set 
    { 
     this.abcSpecified = value; 
    } 
} 
+0

XmlIgnoreAttribute en una propiedad "Specified" no es necesario, así como un setter en la misma propiedad. –

1

Todos los métodos especificados meta como o ShouldSerialize es solo un mal diseño de programación de la estructura Microsoft .Net XML. Se vuelve aún más complicado si no tienes acceso directo a las clases que deseas serializar.

En su método de serialización, deberían simplemente agregar un atributo como "ignoreNullable".

Mi solución actual serializa el xml y luego simplemente elimina todos los nodos que tienen nil = "true" usando la siguiente función.

/// <summary> 
/// Remove optional nullabe xml nodes from given xml string using given scheme prefix. 
/// 
/// In other words all nodes that have 'xsi:nil="true"' are being removed from document. 
/// 
/// If prefix 'xmlns:xsi' is not found in root element namespace input xml content is returned. 
/// </summary> 
/// <param name="xmlContent"></param> 
/// <param name="schemePrefix">Scheme location prefix</param> 
/// <returns></returns> 
public static String RemoveNilTrue(String xmlContent, String schemePrefix = "xsi") 
{ 
    XmlDocument xmlDocument = new XmlDocument(); 
    xmlDocument.LoadXml(xmlContent); 

    XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDocument.NameTable); 

    bool schemeExist = false; 

    foreach (XmlAttribute attr in xmlDocument.DocumentElement.Attributes) 
    { 
     if (attr.Prefix.Equals("xmlns", StringComparison.InvariantCultureIgnoreCase) 
      && attr.LocalName.Equals(schemePrefix, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      nsMgr.AddNamespace(attr.LocalName, attr.Value); 
      schemeExist = true; 
      break; 
     } 
    } 

    // scheme exists - remove nodes 
    if (schemeExist) 
    { 
     XmlNodeList xmlNodeList = xmlDocument.SelectNodes("//*[@" + schemePrefix + ":nil='true']", nsMgr); 

     foreach (XmlNode xmlNode in xmlNodeList) 
      xmlNode.ParentNode.RemoveChild(xmlNode); 

     return xmlDocument.InnerXml; 
    } 
    else 
     return xmlContent; 
} 
+0

Honestamente, Microsoft puede empujarlo por no darnos una opción fácil de eliminar la salida de nil = "verdadero". Aquí hay una idea, Microsoft. Si la propiedad se omite, entonces debe tratarse como nula. Gracias por esta presentación Es una lástima que cosas como esta tengan que hacerse porque Microsoft es tan arrogante. – crush

0

Esta es probablemente la respuesta menos sofisticada, pero la resolví para mí con un simple reemplazo de cadenas.

. Reemplazar ("xsi: nil = \" true \ "", "");

Estoy serializando a la cadena primero de todos modos. Puedo guardar para archivar más tarde.

Mantiene todas mis XmlWriterSettings intactas. Otra solución que encontró a su mal estado arriba :)

private static string Serialize<T>(T details) 
    { 
     var serializer = new XmlSerializer(typeof(T)); 
     using (var ms = new MemoryStream()) 
     { 
      var settings = new XmlWriterSettings 
      { 
       Encoding = Encoding.GetEncoding("ISO-8859-1"), 
       NewLineChars = Environment.NewLine, 
       ConformanceLevel = ConformanceLevel.Document, 
       Indent = true, 
       OmitXmlDeclaration = true 
      }; 

      using (var writer = XmlWriter.Create(ms, settings)) 
      { 
       serializer.Serialize(writer, details); 
       return Encoding.UTF8.GetString(ms.ToArray()).Replace(" xsi:nil=\"true\" ", ""); 
      } 
     } 
    } 
Cuestiones relacionadas