2009-11-10 22 views
9

Tengo una clase C# que tiene más de 20 propiedades de cadena. Coloqué alrededor de un cuarto de ellos en un valor real. Me gustaría serializar la clase y obtener una producción deSuprime xsi: nil pero todavía muestra el elemento vacío al serializar en .Net

<EmptyAttribute></EmptyAttribute> 

una propiedad

public string EmptyAttribute {get;set;} 

no quiero que la salida sea

<EmptyAttribute xsi:nil="true"></EmptyAttribute> 

estoy usando la siguiente clase

public class XmlTextWriterFull : XmlTextWriter 
{ 
    public XmlTextWriterFull(string filename) : base(filename,Encoding.UTF8) { } 

    public override void WriteEndElement() 
    { 
     base.WriteFullEndElement(); 
     base.WriteRaw(Environment.NewLine); 
    } 
} 

de modo que Puedo obtener las etiquetas completas. Simplemente no sé cómo deshacerme de xsi: nil.

+0

Creo que esto es exactamente lo que también necesito, pero su pregunta es incompleta. En lugar de '', ¿desea obtener ''? Si encuentro una respuesta, ¡volveré! – njplumridge

+0

Publiqué mi respuesta a continuación, pruébala y votala si te sirve o si encuentras una mejor manera de publicarla y avisarme. –

Respuesta

-5

De hecho, pude resolver esto. Sé que es un poco de un truco de alguna manera, pero esto es cómo llegué a trabajar

System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(header.GetType()); 
     XmlTextWriterFull writer = new XmlTextWriterFull(FilePath); 
     x.Serialize(writer, header); 
     writer.Flush(); 
     writer.BaseStream.Dispose(); 
     string xml = File.ReadAllText(FilePath); 
     xml = xml.Replace(" xsi:nil=\"true\"", ""); 
     File.WriteAllText(FilePath, xml); 

Esperamos que esto ayude a alguien a cabo

+1

-1 ... Esta es una manera horrible de tratar con XML, por favor evite tales manipulaciones de cadena. Si realmente quiere quitar atributos, use la API XML adecuada ... –

+1

@AlexeiLevenkov: El propósito de la pregunta era encontrar la mejor manera de hacerlo, presumiblemente porque no sabía cómo usar la API para lograr eso. Un poco duro criticar su no usarlo. Una mejor respuesta sería proporcionar una respuesta que demuestre el uso adecuado de XML API. –

+3

@ChrisRogers: ya hay una buena respuesta, así que los comentarios están aquí para alejar a la gente de esto. La manipulación de cadenas no es un buen método para manejar XML. –

12

La manera de tener la XmlSerializer serializar una propiedad sin añadir la xsi:nil="true" El atributo se muestra a continuación:

[XmlRoot("MyClassWithNullableProp", Namespace="urn:myNamespace", IsNullable = false)] 
public class MyClassWithNullableProp 
{ 
    public MyClassWithNullableProp() 
    { 
     this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] { 
      new XmlQualifiedName(string.Empty, "urn:myNamespace") // Default Namespace 
     }); 
    } 

    [XmlElement("Property1", Namespace="urn:myNamespace", IsNullable = false)] 
    public string Property1 
    { 
     get 
     { 
      // To make sure that no element is generated, even when the value of the 
      // property is an empty string, return null. 
      return string.IsNullOrEmpty(this._property1) ? null : this._property1; 
     } 
     set { this._property1 = value; } 
    } 
    private string _property1; 

    // To do the same for value types, you need a "helper property, as demonstrated below. 
    // First, the regular property. 
    [XmlIgnore] // The serializer won't serialize this property properly. 
    public int? MyNullableInt 
    { 
     get { return this._myNullableInt; } 
     set { this._myNullableInt = value; } 
    } 
    private int? _myNullableInt; 

    // And now the helper property that the serializer will use to serialize it. 
    [XmlElement("MyNullableInt", Namespace="urn:myNamespace", IsNullable = false)] 
    public string XmlMyNullableInt 
    { 
     get 
     { 
      return this._myNullableInt.HasValue? 
       this._myNullableInt.Value.ToString() : null; 
     } 
     set { this._myNullableInt = int.Parse(value); } // You should do more error checking... 
    } 

    // Now, a string property where you want an empty element to be displayed, but no 
    // xsi:nil. 
    [XmlElement("MyEmptyString", Namespace="urn:myNamespace", IsNullable = false)] 
    public string MyEmptyString 
    { 
     get 
     { 
      return string.IsNullOrEmpty(this._myEmptyString)? 
       string.Empty : this._myEmptyString; 
     } 
     set { this._myEmptyString = value; } 
    } 
    private string _myEmptyString; 

    // Now, a value type property for which you want an empty tag, and not, say, 0, or 
    // whatever default value the framework gives the type. 
    [XmlIgnore] 
    public float? MyEmptyNullableFloat 
    { 
     get { return this._myEmptyNullableFloat; } 
     set { this._myEmptyNullableFloat = value; } 
    } 
    private float? _myEmptyNullableFloat; 

    // The helper property for serialization. 
    public string XmlMyEmptyNullableFloat 
    { 
     get 
     { 
      return this._myEmptyNullableFloat.HasValue ? 
       this._myEmptyNullableFloat.Value.ToString() : string.Empty; 
     } 
     set 
     { 
      if (!string.IsNullOrEmpty(value)) 
       this._myEmptyNullableFloat = float.Parse(value); 
     } 
    } 

    [XmlNamespaceDeclarations] 
    public XmlSerializerNamespaces Namespaces 
    { 
     get { return this._namespaces; } 
    } 
    private XmlSerializerNamespaces _namespaces; 
} 

Ahora, cree una instancia de esta clase y serialícela.

// I just wanted to show explicitly setting all the properties to null... 
MyClassWithNullableProp myClass = new MyClassWithNullableProp() { 
    Property1 = null, 
    MyNullableInt = null, 
    MyEmptyString = null, 
    MyEmptyNullableFloat = null 
}; 

// Serialize it. 
// You'll need to setup some backing store for the text writer below... 
// a file, memory stream, something... 
XmlTextWriter writer = XmlTextWriter(...) // Instantiate a text writer. 

XmlSerializer xs = new XmlSerializer(typeof(MyClassWithNullableProp), 
    new XmlRootAttribute("MyClassWithNullableProp") { 
     Namespace="urn:myNamespace", 
     IsNullable = false 
    } 
); 

xs.Serialize(writer, myClass, myClass.Namespaces); 

Después de recuperar el contenido de la XmlTextWriter, usted debe tener el siguiente resultado:

<MyClassWithNullableProp> 
    <MyEmptyString /> 
    <MyEmptyNullableFloat /> 
</MyClassWithNullableProp> 

espero que esto demuestra claramente cómo la incorporada en el .NET Framework XmlSerializer se puede utilizar para serializar propiedades a un elemento vacío, incluso cuando el valor de la propiedad sea nulo (o algún otro valor que no desee serializar). Además, he mostrado cómo puede asegurarse de que las propiedades null no se serialicen en absoluto. Una cosa a tener en cuenta, si aplica un XmlElementAttribute y establece la propiedad IsNullable de ese atributo en true, esa propiedad se serializará con el atributo xsi:nil cuando la propiedad sea null (a menos que se haya reemplazado en otro lugar).

+1

Esta es realmente una manera excelente de garantizar que se generen elementos vacíos. Ya tengo listo el código de serialización. Solo estaba interesado en el elemento vacío para la propiedad de cadena.Todo lo que tenía que hacer era agregar un trazador de líneas en la propiedad para marcar String.IsNullOrEmpty y devolver String.Empty si era verdadero. ¡¡Aclamaciones!! –

Cuestiones relacionadas