【问题标题】:XML deserialization cannot resolve attribute typeXML 反序列化无法解析属性类型
【发布时间】:2016-05-24 09:06:47
【问题描述】:

我正在从事一个项目,我通过 REST 和 Comet 语义与 API 服务进行通信。

XML

所以,手头的问题。 当我尝试反序列化以下 XML 时收到此错误。

解析类型“xsi:SubscriptionEvent”时出错 NetBike.Xml.TypeResolvers.XmlTypeResolveException

注意:我使用的是NetBike,但是默认的xml格式化程序中也存在错误

<?xml version="1.0" encoding="UTF-8"?>
<xsi:Event
xsi1:type="xsi:SubscriptionEvent"
xmlns:xsi="http://schema.broadsoft.com/xsi"
xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance">
<xsi:eventID>0787e727-e73d-43e0-a7b1-e968ba72ea53</xsi:eventID>
<xsi:sequenceNumber>1</xsi:sequenceNumber>
<xsi:userId>11111111@voip.company.domain</xsi:userId>
<xsi:externalApplicationId>NewClient</xsi:externalApplicationId>
<xsi:subscriptionId>24def51b-21fb-4d60-a1ef-67477dcafcfb</xsi:subscriptionId>
<xsi:channelId>575cfe44-2cc7-4cf5-bc05-bcc462bcbb02</xsi:channelId>
<xsi:targetId>22222222@voip.company.domain</xsi:targetId>
<xsi:eventData xsi1:type="xsi:ACDSubscriptionEvent"/>
</xsi:Event>

我不是 XML“绝地武士”,但我知道基础知识。 错误告诉我 xsi1:type="xsi:SubscriptionEvent" 类型有问题,这是根 xml(事件)元素上的属性,这是有问题的三个属性。

xsi1:type="xsi:SubscriptionEvent"
xmlns:xsi="http://schema.broadsoft.com/xsi"
xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance"

C#类

我使用的是 C#,到目前为止,我在创建基于开发时返回给我的 XML 的等效类之前没有遇到任何问题。 如果我取出“坏数据”,则可以避免异常。

事件类(我在 Web API V2 环境中使用它,所以从技术上讲它是一个模型)

[XmlRoot(ElementName = "Event", Namespace = "http://schema.broadsoft.com/xsi")]
public class Event
{
    [XmlElement(ElementName = "eventID", Namespace = "http://schema.broadsoft.com/xsi")]
    public string EventID { get; set; }
    [XmlElement(ElementName = "sequenceNumber", Namespace = "http://schema.broadsoft.com/xsi")]
    public string SequenceNumber { get; set; }
    [XmlElement(ElementName = "userId", Namespace = "http://schema.broadsoft.com/xsi")]
    public string UserId { get; set; }
    [XmlElement(ElementName = "externalApplicationId", Namespace = "http://schema.broadsoft.com/xsi")]
    public string ExternalApplicationId { get; set; }
    [XmlElement(ElementName = "subscriptionId", Namespace = "http://schema.broadsoft.com/xsi")]
    public string SubscriptionId { get; set; }
    [XmlElement(ElementName = "channelId", Namespace = "http://schema.broadsoft.com/xsi")]
    public string ChannelId { get; set; }
    [XmlElement(ElementName = "targetId", Namespace = "http://schema.broadsoft.com/xsi")]
    public string TargetId { get; set; }
    [XmlElement(ElementName = "eventData", Namespace = "http://schema.broadsoft.com/xsi")]
    public EventData eventData { get; set; }


    [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string Type { get; set; }
    [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string xsi { get; set; }
    [XmlAttribute(AttributeName = "xsi1", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsi1 { get; set; }

    [XmlRoot(ElementName = "eventData", Namespace = "http://schema.broadsoft.com/xsi")]
    public class EventData
    {
        [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
        public string Type { get; set; }
    }
}

这个类主要是从http://xmltocsharp.azurewebsites.net/生成的 (这大大加快了这项原本枯燥的任务)


有效的 XML?

当我通过不同的 XML 验证器运行 XML 时,我得到不同的响应,有些可以正常验证 XML,有些则不能。

对我来说,我很难理解该结构应该如何工作。 似乎 type 属性应该建立在 xsi1 属性之上,但我尝试的一切都失败了。

我最后的手段是将响应读取为字符串,然后去掉烦人的 XML,以便正确反序列化它。

最好的问候。 一位急需帮助的有点沮丧的开发人员。

【问题讨论】:

    标签: c# xml xml-serialization asp.net-web-api2 xml-deserialization


    【解决方案1】:

    我认为出现了混淆是因为xsi:type 是 XML 模式的一部分并定义了各种元素的类型。您正在尝试将其视为普通属性,并且序列化程序正在尝试使用它来确定要将数据映射到哪些对象。它要查找的对象未在模型中定义。

    本质上,您需要按照 XML 所暗示的类型层次对类进行建模。所以你有一个基类 Event 和一个 SubscriptionEvent 子类,你有一个基类 EventData 和一个 ACDSubscriptionEvent 子类。

    请注意(至少对于XmlSerializer),您可以省略很多命名空间,因为它们是从父级继承的。您可能比我更了解层次结构,因此某些属性可能能够移动到基类等中。理想情况下,您将拥有 XML 模式文件 (.xsd) 并且能够生成类使用xsd.exe,但这适用于给定的 XML:

    [XmlInclude(typeof(SubscriptionEvent))]
    [XmlRoot(Namespace = "http://schema.broadsoft.com/xsi")]
    public abstract class Event
    {
    
    }
    
    [XmlType(Namespace = "http://schema.broadsoft.com/xsi")]
    public class SubscriptionEvent : Event
    {
        [XmlElement(ElementName = "eventID")]
        public string EventID { get; set; }
    
        [XmlElement(ElementName = "sequenceNumber")]
        public string SequenceNumber { get; set; }
    
        [XmlElement(ElementName = "userId")]
        public string UserId { get; set; }
    
        [XmlElement(ElementName = "externalApplicationId")]
        public string ExternalApplicationId { get; set; }
    
        [XmlElement(ElementName = "subscriptionId")]
        public string SubscriptionId { get; set; }
    
        [XmlElement(ElementName = "channelId")]
        public string ChannelId { get; set; }
    
        [XmlElement(ElementName = "targetId")]
        public string TargetId { get; set; }
    
        [XmlElement(ElementName = "eventData")]
        public EventData EventData { get; set; }
    }
    
    [XmlInclude(typeof(ACDSubscriptionEvent))]
    public abstract class EventData
    {
    
    }
    
    [XmlType(Namespace = "http://schema.broadsoft.com/xsi")]
    public class ACDSubscriptionEvent : EventData
    {
    
    }
    

    请参阅 this fiddle 以获取工作演示(使用 XmlSerializer)。

    【讨论】:

    • 这解决了我的问题!我非常感谢你,尽管似乎还有另一个问题可能导致我的头痛。我使用了 XmlFormatters(因为它是 Web API),恐怕它们无法使用您改进的类进行反序列化。幸好你做了一个小提琴,这确实让我看到了这个限制。非常感谢我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2017-06-04
    • 2021-12-30
    • 1970-01-01
    相关资源
    最近更新 更多