5

Mam serię klas, które konwertuję do XML przy użyciu DataContractSerializer .NET w .NET 4.0. Serializacja działa dobrze i mogę parsować XML i odtworzyć obiekty .NET później bez żadnych trudności.Unikanie używania przestrzeni nazw "http://www.w3.org/2001/XMLSchema-instance" z .Net DataContractSerializer

Jednak większość danych DataMember nie jest wymagana. [DataMember (IsRequired = false)]. Działa to wspaniale w przypadku deklasyfikacji kodu XML, w którym można po prostu pominąć węzeł XML poza dokumentem, ale podczas serializacji istniejącego obiektu na XML, DataContractSerializer domaga się wypisywania właściwości, które mają wartości null jako węzły z atrybutem np.

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

} 

można odcinkach od

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

Jednak gdybym serialise obiektu, tworzy:

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

Czy istnieje jakiś sposób, aby uzyskać DataContractSerializer nie napisać węzeł zamiast , kiedy ma wartość pustą?

+0

Zostawiłeś swój przykład. –

+0

Dobrze zauważył ... Coś poszło nie tak z cięciem i wklejaniem ... –

Odpowiedz

10

Zastosowanie EmitDefaultValue = false pominąć wartości domyślne w 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; } 
} 

usunąć xmlns:i="http://www.w3.org/2001/XmlSchema-instance" trzeba użyć np Replace() jak w poniższym przykładzie

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

odniesieniu :)

+0

Pracowałem dla mnie. Dzięki. – TravisWhidden

+4

'String.Replace' do usunięcia wygląda jak hack. Czy jest lepsza opcja? –

0

(Wysłałem tę odpowiedź przypadkowo w niewłaściwym pytaniu, ale myślę, że to też jest pomocne, więc nie usuwam tego teraz)

[DataContract(Namespace = "")] 

na szczycie każdej klasy sprawia, że ​​jest o wiele ładniej. Usuwa przestrzenie nazw datacontract i brzydkie prefiksy węzłów. Jednak standardowa przestrzeń nazw pozostaje. To było w porządku w moim przypadku.

Przed:

<?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> 

Po:

<?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> 
Powiązane problemy