如何使XmlSerializer与xsi:type一起使用?

问题描述 投票:3回答:1

我有以下相当简单的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',at <prop xmlns ='http://foo.com/bar “>。

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

我在这做错了什么?如何将XML转换为C#类?

.net xml-serialization xmlserializer
1个回答
0
投票

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

首先使用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; }
}

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

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

© www.soinside.com 2019 - 2024. All rights reserved.