【问题标题】:Deserialize object property with StringReader vs XmlNodeReader使用 StringReader 与 XmlNodeReader 反序列化对象属性
【发布时间】:2015-05-07 13:18:53
【问题描述】:

为什么XmlSerializer 在使用XmlNodeReader 反序列化空类型元素时使用XmlNode 数组填充我的对象属性,而不是像使用StringReader(或XmlTextReader)时那样使用空字符串?

以下代码示例中的第二个断言失败:

var doc = new XmlDocument();
doc.Load(new StringReader(@"
    <Test xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
          xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
      <Value xsi:type=""xsd:string"" />
    </Test>"));
var ser = new XmlSerializer(typeof (Test));

var reader1 = new StringReader(doc.InnerXml);
var obj1 = (Test) ser.Deserialize(reader1);
Debug.Assert(obj1.Value is string);

var reader2 = new XmlNodeReader(doc.FirstChild);
var obj2 = (Test) ser.Deserialize(reader2);
Debug.Assert(obj2.Value is string);

public class Test
{
    public object Value { get; set; }
}

我猜它与 null 内部 NamespaceManager 属性有关,但我不确定如何解决这个神秘的限制。如何可靠地反序列化已解析 XML 文档的子集,而无需将其转换回字符串并重新解析?

【问题讨论】:

  • 看起来您在第二个实例中将部分文档传递给 XmlSerializer,在第一个实例中传递整个文档,您希望它如何从部分文档中重建类型?跨度>
  • 顺便说一句,如果您调试并查看 obj2 是什么类型,它属于“Test”类,但序列化程序已将您的 obj2.Value 对象反序列化为 XmlNode,而不是字符串。不将整个文档传递给序列化程序是一个有趣的副作用。
  • XmlDocument 的 FirstChild 是整个文档 (doc.FirstChild == doc.DocumentElement)。所以两个阅读器都有相同的信息,只是形式不同(XML 字符串与解析的 XmlNode 图)。
  • 试试这个:Console.WriteLine(doc.FirstChild.ParentNode == null),打印错误。 FirstChild 有一个父节点,即文档。
  • 如果您将 Value 属性类型更改为字符串并将 XML 中的 Value 元素更改为 &lt;Value&gt;Hello&lt;/Value&gt;,那么两个阅读器都可以正常工作。从 XML 片段(部分文档)反序列化正是 XmlNodeReader 的用途。由于某种原因,它似乎无法识别 xsi:type 属性。

标签: c# xml serialization xsd xmlserializer


【解决方案1】:

看起来这是一个非常古老的 XmlNodeReader 错误 Microsoft have no intention of fixing。 (存档的 Microsoft Connect 链接 here)。我在 Lev Gimelfarb 的博客 here 上找到了一种解决方法,它在查找前缀时将命名空间添加到读者的 NameTable

public class ProperXmlNodeReader : XmlNodeReader
{
    public ProperXmlNodeReader(XmlNode node) : base(node)
    {
    }

    public override string LookupNamespace(string prefix)
    {
        return NameTable.Add(base.LookupNamespace(prefix));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2016-05-31
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    相关资源
    最近更新 更多