首页 文章

避免在.Net DataContractSerializer中使用“http://www.w3.org/2001/XMLSchema-instance”命名空间

提问于
浏览
5

我有一系列的类,我在.NET 4.0中使用.NET的DataContractSerializer转换为XML . 序列化工作正常,我可以解析XML并在以后重新创建.NET对象而没有任何困难 .

但是,大多数DataMember都不是必需的 . [DataMember(IsRequired = false)] . 这非常适用于对XML进行反序列化,然后您可以在文档中错过XML节点,但是当将现有对象序列化为XML时,DataContractSerializer坚持将具有空值的属性写为具有属性的节点,例如:

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

}

可以序列化

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

但是,如果我序列化对象,它会创建:

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

当它具有空值时,有没有办法让DataContractSerializer不写节点?

2 回答

  • 1

    使用 EmitDefaultValue = false 跳过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; }
    }
    

    删除 xmlns:i="http://www.w3.org/2001/XmlSchema-instance" 你必须使用例如 Replace() ,如下例所示

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

    带着敬意 :)

  • 10

    (我在错误的问题中意外地发布了这个答案,但我认为这也很有帮助,所以我现在不删除它)

    [DataContract(Namespace = "")]
    

    在每个 class 的顶部使它更好 . 它删除了datacontract命名空间和丑陋的节点前缀 . 但是,标准名称空间保持不变 . 这对我的情况来说没问题 .

    之前:

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

    后:

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

相关问题