3

I have the following fairly simply XML that I'm trying to deserialize:

<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>

When I run XSD.exe over this XML to produce a schema and then run it again to produce C# classes, I end up with highly-decorated versions of the following:

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; }
}

Now when I try to deserialize the XML into these classes using XmlSerializer, I get the following exception:

System.InvalidOperationException: There is an error in XML document (4, 4). --->
System.InvalidOperationException: The specified type was not recognized: name='string', namespace='http://www.w3.org/2001/XMLSchema', at <prop xmlns='http://foo.com/bar'>.

The xsi:type attribute is presumably there to facilitate some polymorphism on the prop value, but I don't care about that - I just want the value in a C# property.

What am I doing wrong here? How can I get that XML into a C# class?

4

1 回答 1

0

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

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

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

 <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; }
}

这应该解决反序列化。

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

于 2019-03-21T17:12:00.823 回答