2009-11-10 7 views
9

Ich habe eine C# -Klasse, die 20+ String-Eigenschaften hat. Ich habe etwa ein Viertel davon auf einen tatsächlichen Wert gesetzt. Ich möchte die Klasse serialisiert werden und eine Leistung vonUnterdrücken Sie xsi: nil, aber zeigen immer noch leeres Element beim Serialisieren in. NET

<EmptyAttribute></EmptyAttribute> 

für eine Eigenschaft

public string EmptyAttribute {get;set;} 

Ich will nicht die Ausgabe

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

Ich verwende die folgende Klasse erhalten

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

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

so dass Ich kann die vollständigen Tags bekommen. Ich weiß einfach nicht, wie ich das xsi: nil loswerden kann.

+0

Ich denke, das ist genau das, was ich auch brauche, aber deine Frage ist unvollständig. Anstatt '' möchten Sie '' erhalten? Wenn ich eine Antwort finde, bin ich wieder da! – njplumridge

+0

Ich habe meine Antwort unten geposted und es voten, wenn es Ihnen hilft oder wenn Sie einen besseren Weg finden und es mich wissen lassen. –

Antwort

-5

Ich war tatsächlich in der Lage, dies herauszufinden. Ich weiß, es ist ein bisschen wie ein Hack in gewisser Weise, aber das ist, wie ich es bekam

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

hoffte, das hilft jemand anderes

+1

-1 ... Dies ist eine schreckliche Art, mit XML umzugehen, bitte vermeiden Sie solche String-Manipulationen. Wenn Sie wirklich Attribute entfernen möchten - verwenden Sie die richtige XML-API ... –

+1

@AlexeiLevenkov: Der ganze Zweck der Frage war, herauszufinden, der beste Weg, dies zu tun - vermutlich, weil er nicht wusste, wie man die API zu erreichen es. Ein bisschen hart zu kritisieren, dass er es nicht benutzt. Eine bessere Antwort wäre, eine Antwort zu geben, die die ordnungsgemäße Verwendung der XML API demonstriert. –

+3

@ChrisRogers - es gibt schon eine gute Antwort - also ist der Kommentar hier, um Leute davon weg zu lenken. String-Manipulation ist praktisch nie ein guter Ansatz, um mit XML umzugehen. –

12

Der Weg zur Arbeit des XmlSerializer serialize eine Eigenschaft zu haben, ohne die xsi:nil="true" Hinzufügen Attribut ist unten gezeigt:

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

Jetzt instanziieren Sie diese Klasse und serialisieren Sie sie.

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

Nach den Inhalt der XmlTextWriter abrufen, sollten Sie die folgende Ausgabe haben:

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

Ich hoffe, das deutlich zeigt, wie die eingebaute in .NET Framework XmlSerializer können Eigenschaften serialisiert werden verwendet werden, um ein leeres Element, selbst wenn der Eigenschaftswert null ist (oder ein anderer Wert, den Sie nicht serialisieren möchten). Außerdem habe ich gezeigt, wie Sie sicherstellen können, dass null Eigenschaften überhaupt nicht serialisiert sind. Eine Sache zu beachten, wenn Sie eine anwenden und die IsNullable Eigenschaft dieses Attributs auf true setzen, dann wird diese Eigenschaft mit dem xsi:nil Attribut serialisieren, wenn die Eigenschaft null ist (sofern nicht anderswo überschrieben).

+1

Dies ist wirklich eine hervorragende Möglichkeit sicherzustellen, dass leere Elemente generiert werden. Ich habe bereits den Serialisierungscode bereit. Ich war nur an einem leeren Element für die String-Eigenschaft interessiert.Alles, was ich tun musste, war, einen einzigen Liner in der Eigenschaft hinzuzufügen, um String.IsNullOrEmpty zu überprüfen und String.Empty zurückzugeben, falls true. Prost!! –