我可以让 XmlSerializer 在反序列化时忽略命名空间吗?
Posted
技术标签:
【中文标题】我可以让 XmlSerializer 在反序列化时忽略命名空间吗?【英文标题】:Can I make XmlSerializer ignore the namespace on deserialization? 【发布时间】:2010-10-26 14:21:42 【问题描述】:我是否可以让 XmlSerializer 在反序列化时忽略名称空间(xmlns 属性),这样无论是否添加该属性或即使该属性是伪造的都无关紧要?我知道来源将始终受到信任,所以我不关心 xmlns 属性。
【问题讨论】:
小心,如果你覆盖NamespaceURI
,它不仅会影响所有元素,还会影响属性。有时这会导致反序列化器忽略将它们全部设置为 null 的属性。
显然存在忽略命名空间的缺陷。你可以对元素说同样的话——如果反序列化程序需要一个命名空间限定的元素,并且在没有命名空间的元素中找到一个元素,那么它不会在反序列化的实例中设置关联的属性。这些只是道路规则。它在我给出的示例中有效,因为所有元素都没有命名空间。
【参考方案1】:
是的,您可以告诉 XmlSerializer 在反序列化期间忽略命名空间。
定义一个忽略命名空间的 XmlTextReader。像这样:
// helper class to ignore namespaces when de-serializing
public class NamespaceIgnorantXmlTextReader : XmlTextReader
public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader): base(reader)
public override string NamespaceURI
get return "";
// helper class to omit XML decl at start of document when serializing
public class XTWFND : XmlTextWriter
public XTWFND (System.IO.TextWriter w) : base(w) Formatting= System.Xml.Formatting.Indented;
public override void WriteStartDocument ()
这是一个如何使用 TextReader 进行反序列化的示例:
public class MyType1
public string Label
set _Label= value;
get return _Label;
private int _Epoch;
public int Epoch
set _Epoch= value;
get return _Epoch;
String RawXml_WithNamespaces = @"
<MyType1 xmlns='urn:booboo-dee-doo'>
<Label>This document has namespaces on its elements</Label>
<Epoch xmlns='urn:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>0</Epoch>
</MyType1>";
System.IO.StringReader sr;
sr= new System.IO.StringReader(RawXml_WithNamespaces);
var s1 = new XmlSerializer(typeof(MyType1));
var o1= (MyType1) s1.Deserialize(new NamespaceIgnorantXmlTextReader(sr));
System.Console.WriteLine("\n\nDe-serialized, then serialized again:\n");
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("urn", "booboo-dee-doo");
s1.Serialize(new XTWFND(System.Console.Out), o1, ns);
Console.WriteLine("\n\n");
结果是这样的:
<MyType1>
<Label>This document has namespaces on its elements</Label>
<Epoch>0</Epoch>
</MyType1>
【讨论】:
注意这是我的意思。您不是在告诉 XmlSerializer 忽略名称空间 - 您是在给它提供没有名称空间的 XML。 ???我不明白。我给了它在元素上具有名称空间的 XML。代码反序列化(读取)XML 文档并忽略命名空间。【参考方案2】:扩展 Wolfgang Grinfeld 答案(无异常处理):
public static Message Convert(XmlDocument doc)
Message obj;
using (TextReader textReader = new StringReader(doc.OuterXml))
using (XmlTextReader reader = new XmlTextReader(textReader))
reader.Namespaces = false;
XmlSerializer serializer = new XmlSerializer(typeof(Message));
obj = (Message)serializer.Deserialize(reader);
return obj;
【讨论】:
它并没有真正忽略。如果设置为 false,则要求您不包含命名空间。 这对我很有效。我的用例是在反序列化为对象时忽略在 XML 文档中收到的命名空间,这样无论命名空间是否存在,行为都是一致的。谢谢。【参考方案3】:如果你期望没有命名空间,但输入有命名空间,那么你可以设置
命名空间 = 假
在您的 XmlTextReader 上。
【讨论】:
【参考方案4】:这不会忽略命名空间,而是期望它。我试图做和你一样的事情,但我已经使用 XSD 添加了验证,现在需要命名空间。所以这就是我以前期望的命名空间。 https://***.com/a/7730989/1856992
【讨论】:
【参考方案5】:通过使用 XmlSerializer Deserialize 从 xml 而不是从流中读取来解决此问题。这种方式在 xml 被反序列化之前,使用 Regex 从 xml 中删除 xsi:type。这样做是跨平台的可移植类库,所以没有很多其他选择:(。在此之后反序列化似乎工作正常。
以下代码可以提供帮助,
public static TClass Deserialize<TClass>(string xml) where TClass : class, new()
var tClass = new TClass();
xml = RemoveTypeTagFromXml(xml);
var xmlSerializer = new XmlSerializer(typeof(TClass));
using (TextReader textReader = new StringReader(xml))
tClass = (TClass)xmlSerializer.Deserialize(textReader);
return tClass;
public static string RemoveTypeTagFromXml(string xml)
if (!string.IsNullOrEmpty(xml) && xml.Contains("xsi:type"))
xml = Regex.Replace(xml, @"\s+xsi:type=""\w+""", "");
return xml;
【讨论】:
可以将命名空间通知给XmlSerializer,所以不需要从XML中移除: XmlSerializer serializer = new XmlSerializer(typeof(T), elementXml.GetDefaultNamespace().NamespaceName); return (T)serializer.Deserialize(elementXml.CreateReader());【参考方案6】:为什么要让 XmlSerializer 忘记 XML 的工作原理? XML 的一个事实是,两个具有相同名称但不同命名空间的元素是不同的元素。
如果你想处理没有命名空间的 XML,那么你应该预处理它以移除命名空间,然后然后将它传递给序列化器。
【讨论】:
约翰,你说的是真的,但是,你有时会从那些认为 xml 只是格式很好的数据后面的开始标签 .. 使用尖括号的结束标签样式的人那里得到“xml”数据;他们完全没有注意到整个命名空间概念;我的猜测是,NotDan 是那些需要使用这类人提供的 xml 数据的可怜人之一。我经历过something similar. @John:有时你必须选择你的战斗。对一些相对琐碎的事情说“不”,客户说“如果你做不到,还有很多其他人可以做到。Hasta la vista,宝贝!”。我们可以指出潜在的问题,但最终是他们的决定和决定。如果我们想保持他们的业务,我们必须尊重该决定并解决它。 @simon 这种态度是导致问题持续存在的原因,即使在七年后也是如此。我应该说“不,但我们很乐意帮助您学习生成有效的 XML”。 @John,是的,除非您必须与 zml 交互,否则您无法控制。请告诉 UPS、FedEx 和 USPS 修复其损坏的 Web 服务。我会喜欢的。 让我重申最后一段。与其让所有的“xml 程序”都处理不同的非 XML 语言,不如使用预处理器。这将使您的源代码的疯狂与您的程序员隔离开来,他们将能够使用标准 XML API 来处理 XML。以上是关于我可以让 XmlSerializer 在反序列化时忽略命名空间吗?的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 c# xmlserializer 反序列化以前序列化的 XML