使用DataContractSerializer序列化没有名称空间的对象
问题描述:
如何从使用DataContractSerializer序列化的对象的XML表示中删除XML名称空间?使用DataContractSerializer序列化没有名称空间的对象
该对象需要序列化为非常简单的输出XML。
- 最新&最大 - 使用.NET 4.0 Beta 2的
- 对象将永远不需要反序列化。
- XML不应该有任何xmlns:... namespace refs
- 需要支持Exception和ISubObject的任何子类型。
- 改变原始物体将会非常困难。
对象:
[Serializable]
class MyObj
{
string str;
Exception ex;
ISubObject subobj;
}
需要序列化到:
<xml>
<str>...</str>
<ex i:nil="true" />
<subobj i:type="Abc">
<AbcProp1>...</AbcProp1>
<AbcProp2>...</AbcProp2>
</subobj>
</xml>
我用这个代码:
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();
}
}
从this article我收养了一个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);
}
}
答
你必须标记你想用序列化类:
[DataContract(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, "");
}
}
在刻录机的消费者
然后,像下面这样:
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);
}
}
和输出将命名空间声明中,但不会有用途为这样:
<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>
一些子对象不在我的控制之下,我无法改变它们。是否可以在不改变对象的情况下做到这一点? – Yurik 2009-12-05 10:36:16
不,对不起 - 你不能移除现有的命名空间 - 你必须能够在对象本身上指定命名空间。 – 2009-12-05 11:17:25
那不可能 - 所有的系统类型呢? MS不能期望所有类型都是可修改的,必须有其他的一些方法:( – Yurik 2009-12-05 13:04:09