.net 使用 DataContractSerializer 序列化没有命名空间的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1851559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:37:15  来源:igfitidea点击:

Serializing object with no namespaces using DataContractSerializer

.netxml-serializationnamespacesdatacontractserializer

提问by Yurik

How do I remove XML namespaces from an object's XML representation serialized using DataContractSerializer?

如何从使用 DataContractSerializer 序列化的对象的 XML 表示中删除 XML 命名空间?

That object needs to be serialized to a very simple output XML.

该对象需要序列化为一个非常简单的输出 XML。

  • Latest & greatest - using .Net 4 beta 2
  • The object will never need to be deserialized.
  • XML should not have any xmlns:... namespace refs
  • Any subtypes of Exception and ISubObject need to be supported.
  • It will be very difficult to change the original object.
  • 最新和最好的 - 使用 .Net 4 beta 2
  • 该对象永远不需要反序列化。
  • XML 不应有任何 xmlns:... 命名空间引用
  • 需要支持 Exception 和 ISubObject 的任何子类型。
  • 更改原始对象将非常困难。

Object:

目的:

 [Serializable] 
 class MyObj
 {
     string str;
     Exception ex;
     ISubObject subobj;
 } 

Need to serialize into:

需要序列化为:

<xml>
  <str>...</str>
  <ex i:nil="true" />
  <subobj i:type="Abc">
     <AbcProp1>...</AbcProp1>
     <AbcProp2>...</AbcProp2>
  </subobj>
</xml>

I used this code:

我使用了这个代码:

private static string ObjectToXmlString(object obj)
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer =
        new DataContractSerializer(
            obj.GetType(), null, Int32.MaxValue, false, false, null,
            new AllowAllContractResolver());

    var sb = new StringBuilder();
    using (var xw = XmlWriter.Create(sb, new XmlWriterSettings
    {
        OmitXmlDeclaration = true,
        NamespaceHandling = NamespaceHandling.OmitDuplicates,
        Indent = true
    }))
    {
        serializer.WriteObject(xw, obj);
        xw.Flush();

        return sb.ToString();
    }
}

From this articleI adopted a DataContractResolver so that no subtypes have to be declared:

本文中,我采用了 DataContractResolver 以便不必声明子类型:

public class AllowAllContractResolver : DataContractResolver
{
    public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
    {
        if (!knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace))
        {
            var dictionary = new XmlDictionary();
            typeName = dictionary.Add(dataContractType.FullName);
            typeNamespace = dictionary.Add(dataContractType.Assembly.FullName);
        }
        return true;
    }

    public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
    {
        return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? Type.GetType(typeName + ", " + typeNamespace);
    }
}

回答by marc_s

You need to mark the classes you want to serialize with:

您需要标记要序列化的类:

[DataContract(Namespace="")]

In that case, the data contract serializer will not use any namespace for your serialized objects.

在这种情况下,数据协定序列化程序不会为您的序列化对象使用任何命名空间。

Marc

马克

回答by leat

If you have your heart set on bypassing the default behavior (as I currently do), you create a custom XmlWriter that bypasses writing the namespace.

如果您想绕过默认行为(就像我目前所做的那样),您可以创建一个自定义 XmlWriter 来绕过写入命名空间。

using System.IO;
using System.Xml;

public class MyXmlTextWriter : XmlTextWriter
{
  public MyXmlTextWriter(Stream stream)
    : base(stream, null)
  {
  }

  public override void WriteStartElement(string prefix, string localName, string ns)
  {
    base.WriteStartElement(null, localName, "");
  }
}

Then in your writer consumer, something like the following:

然后在您的作家消费者中,类似于以下内容:

var xmlDoc = new XmlDocument();
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var ms = new MemoryStream())
{
  using (var writer = new MyXmlTextWriter(ms))
  {
    serializer.WriteObject(writer, obj);
    writer.Flush();
    ms.Seek(0L, SeekOrigin.Begin);
    xmlDoc.Load(ms);
  }
}

And the output will have namespace declarations in it, but there will be no usages as such:

并且输出中将包含命名空间声明,但不会有这样的用法:

<TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Items xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <string>Item1</string>
    <string>Item2</string>
  </Items>
</TestObject>