【问题标题】:How can I make XmlSerializer work with xsi:type?如何使 XmlSerializer 与 xsi:type 一起使用?
【发布时间】:2012-05-16 15:34:47
【问题描述】:

我尝试反序列化以下相当简单的 XML:

<props xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://foo.com/bar">
  <prop name="foo1" xsi:type="xsd:string">bar1</prop>
  <prop name="foo2" xsi:type="xsd:int">2</prop>
</props>

当我在此 XML 上运行 XSD.exe 以生成架构,然后再次运行以生成 C# 类时,我最终得到了以下经过高度修饰的版本:

public partial class props
{
    [XmlElement("prop", IsNullable = true)]
    propsProp[] Items { get; set; }
}

public partial class propsProp
{
    [XmlAttribute]
    public string name { get; set; }
    [XmlText]
    public string Value { get; set; }
}

现在,当我尝试使用 XmlSerializer 将 XML 反序列化为这些类时,出现以下异常:

System.InvalidOperationException:XML 文档中存在错误 (4, 4)。 --->
System.InvalidOperationException:无法识别指定的类型:name='string',namespace='http://www.w3.org/2001/XMLSchema',在 .

xsi:type 属性可能是为了促进 prop 值的一些多态性,但我不在乎 - 我只想要 C# 属性中的值。

我在这里做错了什么?如何将该 XML 放入 C# 类中?

【问题讨论】:

  • 我不确定如果没有额外的努力,这将如何工作,因为除非您使用泛型 (propsProp&lt;T&gt; - public T Value { get; set; },否则该类不能具有 intstring 的值。跨度>
  • 这似乎表明XmlSerializer 根本不适用于xsi:type?如果有帮助,我很乐意在反序列化中忽略它..?
  • 所以您永远不必将其序列化回原始 XML?
  • 就我而言,我不会。 (但很好。)

标签: .net xml-serialization xmlserializer


【解决方案1】:

我遇到了完全相同的问题,它的解决方案对于引用预定义类型非常简单,但对于原始类型来说有点棘手。

首先使用使用xsi:type 有什么好处。我发现这个link 很有帮助,它可以帮助我解决问题。

所以我们在 XML 中使用xsi:type 来指代驱动类型,例如:

 <X xsi:type="X1">

意味着 X 和 X1 是相互驱动的类型,所以我通过使用继承来修复反序列化,通过为子类型创建一个新类并使其从父类型继承,我们还需要创建它的列表:

    [XmlRoot(ElementName = "X1")]
    public class X1: X
    {
    }

    [XmlRoot(ElementName = "X1List")]
    public class X1List
    {
        [XmlElement(ElementName = "X1")]
        public X1 X1{ get; set; }
    }

在另一个已经使用 X 的类中还添加 X1,如下所示:

[XmlRoot(ElementName = "Container")]
public class Container
{
    ...
    [XmlElement(ElementName = "XList")]
    public POCList XList{ get; set; }
    [XmlElement(ElementName = "X1List")]
    public X1List X1List{ get; set; }
    ...
    [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsi { get; set; }
}

这应该可以解决反序列化问题。

对于原始类型,这将是一个棘手的问题,但您可以使用带有约束的泛型来实现相同的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多