【问题标题】:Removing namespaces serializing with DataContractSerializer删除使用 DataContractSerializer 序列化的命名空间
【发布时间】:2016-09-28 02:39:38
【问题描述】:

我使用DataContractSerializer 来序列化一个对象。这是我的代码:

private string XmlSerial<T>(T instance)
{
    DataContractSerializer Serializer = new DataContractSerializer(typeof(T));
    using (MemoryStream memoryStream = new MemoryStream())
    {
        Serializer.WriteObject(memoryStream, instance);
        return Encoding.Default.GetString(memoryStream.ToArray());
    }
}

这是我的输出:

<WS_IN_GetAccountCredit xmlns="http://schemas.datacontract.org/2004/07/WcfWebService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <GetAccountCreditParams xmlns:a="http://schemas.datacontract.org/2004/07/RestConsumer">
    <a:Password>String content</a:Password>
    <a:UserName>String content</a:UserName>
  </GetAccountCreditParams>
  <WSIdentity xmlns:a="http://schemas.datacontract.org/2004/07/RestConsumer">
    <a:WS_PassWord>String content</a:WS_PassWord>
    <a:WS_UserName>String content</a:WS_UserName>
  </WSIdentity>
</WS_IN_GetAccountCredit>

我现在需要删除 xmlns:i 和 xmlns:a 并设置Indent = true;,我该怎么做?

【问题讨论】:

  • 你又遇到了一个新问题。这和之前的类结构一样吗?

标签: c#


【解决方案1】:

首先,您需要用[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/WcfWebService")] 标记所有类,以声明每个类都应在该命名空间中序列化。完成此操作后,您还必须使用[DataMember] 标记要序列化的每个或属性,因为DataContractSerializer 是可选的。

因此:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/WcfWebService")]
public class WS_IN_GetAccountCredit
{
    [DataMember]
    public GetAccountCreditParams GetAccountCreditParams { get; set; }
    [DataMember]
    public WSIdentity WSIdentity { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/WcfWebService")]
public class GetAccountCreditParams
{
    [DataMember]
    public string Password { get; set; }
    [DataMember]
    public string UserName { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/WcfWebService")]
public class WSIdentity
{
    [DataMember]
    public string WS_PassWord { get; set; }
    [DataMember]
    public string WS_UserName { get; set; }
}

其次,对于缩进,您可以创建一个具有所需缩进的XmlWriterSettings,然后从中创建一个XmlWriter 并将其用于序列化,如以下扩展方法:

public static class DataContractSerializerHelper
{
    public static string GetXml<T>(T obj, DataContractSerializer serializer)
    {
        using (var textWriter = new StringWriter())
        {
            var settings = new XmlWriterSettings { Indent = true, IndentChars = "    " };
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                serializer.WriteObject(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
    }

    public static string GetXml<T>(T obj)
    {
        var serializer = new DataContractSerializer(typeof(T));
        return GetXml(obj, serializer);
    }
}

第三,至于删除标准命名空间xmlns:i="http://www.w3.org/2001/XMLSchema-instance",我认为这可能与DataContractSerializer 直接相关。 (XmlSerializer 允许更多控制。)它是无害的,但您可以按照Avoiding using the “http://www.w3.org/2001/XMLSchema-instance” namespace with .Net DataContractSerializer 中的说明手动删除它。

【讨论】:

  • 只是简单地将对象序列化为xml就如此复杂,这绝对是疯了。他们强加给我们的所有这些命名空间只是不必要的复杂性。
【解决方案2】:
[DataContract(Namespace = "")]

在每个类的顶部使它变得更好。它删除了 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>

【讨论】:

  • 知道如何完全删除命名空间吗?
  • @leen3o 你试过魔法命名空间名称 urn:uuid:e657a351-ae8c-42c5-b083-ebe5dcda5c0b 吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 1970-01-01
相关资源
最近更新 更多