2009-11-10 6 views
9

Ho una classe C# con oltre 20 proprietà di stringa. Ho impostato circa un quarto di quelli per un valore effettivo. Vorrei serializzare la classe e ottenere una potenza diSopprime xsi: nil ma mostra ancora Elemento vuoto durante la serializzazione in .Net

<EmptyAttribute></EmptyAttribute> 

per una proprietà

public string EmptyAttribute {get;set;} 

Non voglio l'uscita sia

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

Sto usando la seguente classe

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

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

così che Posso ottenere i tag completi. Non so proprio come sbarazzarmi di xsi: nil.

+0

Penso che questo sia esattamente ciò di cui ho bisogno, ma la tua domanda è incompleta. Invece di '' vorresti ottenere ''? Se trovo una risposta, tornerò! – njplumridge

+0

Ho postato la mia risposta qui sotto e la vota se ti aiuta o se trovi una soluzione migliore pubblicala e fammi sapere. –

risposta

-5

In realtà sono riuscito a capirlo. So che è un po 'di hack in qualche modo, ma questo è come ho preso a lavorare

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

Spero che questo aiuti qualcun altro fuori

+1

-1 ... Questo è un modo terribile per gestire XML, per favore evita tali manipolazioni di stringhe. Se vuoi veramente rimuovere gli attributi - usa l'API XML corretta ... –

+1

@AlexeiLevenkov: Lo scopo della domanda era scoprire il modo migliore per farlo - presumibilmente perché non sapeva come usare l'API per raggiungere esso. Un po 'duro criticare il suo non usarlo. Una risposta migliore sarebbe quella di fornire una risposta che dimostra il corretto utilizzo dell'API XML. –

+3

@ChrisRogers - c'è già una buona risposta - quindi il commento è qui per orientare le persone da questo. La manipolazione delle stringhe non è mai un buon approccio per gestire XML. –

12

Il modo per avere la XmlSerializer serializzare una proprietà senza aggiungere il xsi:nil="true" l'attributo è mostrato di seguito:

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

Ora, creare un'istanza di questa classe e serializzarla.

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

Dopo aver recuperato il contenuto del XmlTextWriter, si dovrebbe avere il seguente output:

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

Spero che questo dimostra chiaramente come il built-in .NET Framework XmlSerializer può essere utilizzato per serializzare oggetti da un elemento vuoto, anche quando il valore della proprietà è nullo (o qualche altro valore che non si desidera serializzare). Inoltre, ho mostrato come è possibile assicurarsi che le proprietà null non siano affatto serializzate. Una cosa da notare, se si applica un XmlElementAttribute e si imposta la proprietà IsNullable di true, tale proprietà verrà serializzata con l'attributo xsi:nil quando la proprietà è null (a meno che non venga sovrascritta da qualche altra parte).

+1

Questo è davvero un ottimo modo per garantire che vengano generati elementi vuoti. Ho già pronto il codice di serializzazione. Mi interessava solo l'elemento vuoto per la proprietà stringa.Tutto quello che dovevo fare era aggiungere un solo liner nella proprietà per verificare String.IsNullOrEmpty e restituire String.Empty se true. Saluti!! –

Problemi correlati