5

Ho una serie di classi che sto convertendo in XML utilizzando DataContractSerializer di .NET in .NET 4.0. La serializzazione funziona correttamente e posso analizzare l'XML e ricreare gli oggetti .NET in seguito senza alcuna difficoltà.Evitare di utilizzare lo spazio dei nomi "http://www.w3.org/2001/XMLSchema-instance" con .Net DataContractSerializer

Tuttavia, la maggior parte dei DataMember non sono richiesti. [DataMember (IsRequired = false)]. Questo funziona perfettamente con la de-serializzazione dell'XML, in cui è possibile semplicemente perdere il nodo XML dal documento, ma quando serializzi un oggetto esistente in XML, DataContractSerializer insiste sulla scrittura di proprietà che hanno valori nulli come nodi con un attributo, ad es.

[DataContract(Name = "response", Namespace = "http://domain.com/name")] 
public class MyResponseClass 
{ 
    [DataMember(Name = "count", IsRequired = true, Order = 0)] 
    public int Count { get; set; } 

    [DataMember(Name = "info", IsRequired = false, Order = 1)] 
    public InfoClass Info { get; set; } 

    [DataMember(Name = "metadata", IsRequired = false, Order = 2)] 
    public MetadataList Metadatas { get; set; } 

} 

può essere serializzato dal

<response xmlns="http://domain.com/name"> 
    <count>4</count> 
</response> 

Tuttavia, se puntate l'oggetto, si crea:

<response xmlns="http://domain.com/name" xmlns:i="http://www.w3.org/2001/XmlSchema-instance"> 
    <count>4</count> 
    <info i:nil="true" /> 
    <metadata i:nil="true" /> 
</response> 

Esiste un modo per ottenere il DataContractSerializer di non scrivere il nodo invece , quando ha un valore nullo?

+0

hai lasciato fuori il tuo esempio. –

+0

Ben chiazzato ... Qualcosa è andato storto con il taglia e incolla ... –

risposta

10

Usa EmitDefaultValue = false per saltare i valori di default in XML:

[DataContract(Name = "response", Namespace = "http://domain.com/name")] 
public class MyResponseClass 
{ 
    [DataMember(Name = "count", IsRequired = true, Order = 0, EmitDefaultValue = false)] 
    public int Count { get; set; } 

    [DataMember(Name = "info", IsRequired = false, Order = 1, EmitDefaultValue = false)] 
    public InfoClass Info { get; set; } 

    [DataMember(Name = "metadata", IsRequired = false, Order = 2, EmitDefaultValue = false)] 
    public MetadataList Metadatas { get; set; } 
} 

per rimuovere xmlns:i="http://www.w3.org/2001/XmlSchema-instance" è necessario utilizzare ad esempio Replace() come nel seguente esempio

public void Write(string filePath, MyResponseClass myResponse) 
{ 
    var serializer = new DataContractSerializer(typeof(MyResponseClass)); 

    var sb = new StringBuilder(); 
    using (var writer = new StringWriter(sb)) 
    using (var xmlWriter = XmlWriter.Create(writer)) 
    { 
     serializer.WriteObject(xmlWriter, myResponse); 
    } 

    using (StreamWriter stream = new StreamWriter(filePath)) 
    { 
     sb = sb.Replace(" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"", ""); 
     stream.Write(sb); 
    } 
} 

per quanto riguarda :)

+0

Ha funzionato per me. Grazie. – TravisWhidden

+4

'String.Replace' per rimuoverlo sembra un hack. C'è un'opzione migliore? –

0

(Ho postato questa risposta accidentalmente nella domanda sbagliata, ma penso che sia utile anche qui, quindi non lo elimini per ora)

[DataContract(Namespace = "")] 

in cima a ogni classe lo rende molto più bello. Rimuove gli spazi dei nomi datacontract e i prefissi dei brutti nodi. Tuttavia, lo spazio dei nomi standard rimane. Era ok per il mio caso.

Prima:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://schemas.datacontract.org/2004/07/MyClassname"> 
    <prop1>true</prop1> 
    <prop2 xmlns:d2p1="http://schemas.datacontract.org/2004/07/MySubclassname"> 
    <d2p1:sub>true</d2p1:sub> 
    </prop2> 
</root> 

Dopo:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <prop1>true</prop1> 
    <prop2> 
    <sub>true</sub> 
    </prop2> 
</root> 
Problemi correlati