5

Tôi có một loạt các lớp mà tôi đang chuyển đổi sang XML bằng cách sử dụng .NET DataContractSerializer trong .NET 4.0. Việc tuần tự hóa hoạt động tốt và tôi có thể phân tích cú pháp XML và tạo lại các đối tượng .NET sau này mà không gặp bất kỳ khó khăn nào.Tránh sử dụng không gian tên “http://www.w3.org/2001/XMLSchema-instance” với .Net DataContractSerializer

Tuy nhiên, hầu hết các DataMember đều không bắt buộc. [DataMember (IsRequired = false)]. Điều này làm việc tuyệt vời khi hủy xê-ri XML, nơi bạn có thể bỏ qua nút XML trong tài liệu, nhưng khi tuần tự hóa một đối tượng hiện có thành XML, DataContractSerializer nhấn mạnh vào việc ghi ra các thuộc tính có giá trị null như các nút có thuộc tính, ví dụ:

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

} 

thể được tuần tự từ

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

Tuy nhiên, nếu tôi serialise đối tượng, nó tạo ra:

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

Có cách nào để có được những DataContractSerializer để không viết nút thay vì , khi nó có giá trị null?

+0

Bạn bỏ qua ví dụ của bạn. –

+0

Cũng phát hiện ... Đã xảy ra sự cố với việc cắt và dán ... –

Trả lời

10

Sử dụng EmitDefaultValue = false để bỏ qua các giá trị mặc định trong 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; } 
} 

để loại bỏ xmlns:i="http://www.w3.org/2001/XmlSchema-instance" bạn phải sử dụng ví dụ Replace() như trong ví dụ sau

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

liên quan :)

+0

Đã làm việc cho tôi. Cảm ơn. – TravisWhidden

+4

'String.Replace' để xóa nó trông giống như một hack. Có lựa chọn nào tốt hơn không? –

0

(Tôi đã đăng câu trả lời này một cách vô tình trong câu hỏi sai, nhưng tôi nghĩ nó cũng hữu ích ở đây, vì vậy tôi không xóa nó cho bây giờ)

[DataContract(Namespace = "")] 

trên đầu mỗi lớp làm cho nó đẹp hơn rất nhiều. Nó loại bỏ các không gian tên datacontract và các tiền tố nút xấu xí. Tuy nhiên, không gian tên chuẩn vẫn tồn tại. Đó là ok cho trường hợp của tôi.

Trước:

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

Sau:

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