【问题标题】:XML parse to object, get invalid operation exceptionXML 解析到对象,得到无效的操作异常
【发布时间】:2022-01-23 09:08:15
【问题描述】:

我尝试为 Flurl 添加扩展方法,将 http 响应从 xml 解析到对象。 有代码

 public static async Task<T> ReceiveXml<T>(this Task<IFlurlResponse> content)
    {
        var response = await content.ConfigureAwait(false);
        if (response == null) return default(T);
        try
        {
            var originData = await response.GetStreamAsync().ConfigureAwait(false);
            var serializer = new XmlSerializer(typeof(T));
            var result = (T)serializer.Deserialize(originData);
            return result;
        }
        catch (Exception)
        {
            response.Dispose();
            throw;
        }
    }

但是当我试图解析这个 xml 时

<Service.ABC
xmlns="http://schemas.datacontract.org/2004/07/Services.Public"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Amount>0</Amount>
<CustomerID i:nil="true"/>
<ID>0</ID>
<UpdatedDate i:nil="true"/>
</Service.ABC>

我收到了一个错误

System.InvalidOperationException: 不是预期的。

我建立的模型来自

https://json2csharp.com/xml-to-csharp

[XmlRoot(ElementName="CustomerID")]
public class CustomerID { 

    [XmlAttribute(AttributeName="nil")] 
    public bool Nil { get; set; } 
}

[XmlRoot(ElementName="UpdatedDate")]
public class UpdatedDate { 

    [XmlAttribute(AttributeName="nil")] 
    public bool Nil { get; set; } 
}

[XmlRoot(ElementName="Service.ABC")]
public class ServiceABC { 

    [XmlElement(ElementName="Amount")] 
    public int Amount { get; set; } 

    [XmlElement(ElementName="CustomerID")] 
    public CustomerID CustomerID { get; set; } 

    [XmlElement(ElementName="ID")] 
    public int ID { get; set; } 

    [XmlElement(ElementName="UpdatedDate")] 
    public UpdatedDate UpdatedDate { get; set; } 

    [XmlAttribute(AttributeName="xmlns")] 
    public string Xmlns { get; set; } 

    [XmlAttribute(AttributeName="i")] 
    public string I { get; set; } 

    [XmlText] 
    public int Text { get; set; } 
}

如果使用 XmlDocument 并加载此 xml 文件可以成功解析,所以...我认为该文件是正确的。 但是 XmlSerializer 有什么问题呢?

【问题讨论】:

    标签: c# .net-6.0


    【解决方案1】:

    您使用的网站似乎不可靠。您是否注意到它为您提供了 3 个XmlRoot 课程?

    使用 Visual Studio 中的 Paste XML as classes 功能,我得到了这样的结果:

    // NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.datacontract.org/2004/07/Services.Public")]
    [System.Xml.Serialization.XmlRootAttribute("Service.ABC", Namespace = "http://schemas.datacontract.org/2004/07/Services.Public", IsNullable = false)]
    public partial class ServiceABC
    {
    
        private byte amountField;
    
        private object customerIDField;
    
        private byte idField;
    
        private object updatedDateField;
    
        /// <remarks/>
        public byte Amount
        {
            get
            {
                return this.amountField;
            }
            set
            {
                this.amountField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(IsNullable = true)]
        public object CustomerID
        {
            get
            {
                return this.customerIDField;
            }
            set
            {
                this.customerIDField = value;
            }
        }
    
        /// <remarks/>
        public byte ID
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(IsNullable = true)]
        public object UpdatedDate
        {
            get
            {
                return this.updatedDateField;
            }
            set
            {
                this.updatedDateField = value;
            }
        }
    }
    

    【讨论】:

    • 我用骑手 Q_Q 编写 C#,但是谢谢,它也有效。
    【解决方案2】:

    您的根对象 ServiceABC 上缺少命名空间声明。

    您似乎还有不正确的嵌套对象:nil="true" 只是表示它是一个可为空的字段。由于缺乏信息,我不得不猜测真正的类型是什么。

    [XmlRoot(ElementName="Service.ABC", Namespace = "http://schemas.datacontract.org/2004/07/Services.Public")]
    public class ServiceABC
    { 
        [XmlElement(ElementName="Amount")] 
        public int? Amount { get; set; } 
    
        [XmlElement(ElementName="CustomerID")] 
        public int? CustomerID { get; set; } 
    
        [XmlElement(ElementName="ID")] 
        public int ID { get; set; } 
    
        [XmlElement(ElementName="UpdatedDate")] 
        public DateTime? UpdatedDate { get; set; } 
    }
    

    dotnetfiddle

    【讨论】:

    • 我得到了同样的异常 System.InvalidOperationException: There is an error in XML document (1, 2)。 ---> System.InvalidOperationException: 不是预期的。
    • 正如我所展示的,它适用于您提供的 XML。请使用包含失败 XML 的 minimal reproducible example 创建一个 dotnetfiddle.net
    • 对不起,我在我的代码中发现了拼写错误.. 成功了!!谢谢你!!!
    猜你喜欢
    • 2017-04-16
    • 2013-01-15
    • 2017-06-21
    • 2014-05-16
    • 2016-03-24
    • 2010-10-02
    • 2014-03-18
    • 2012-09-02
    相关资源
    最近更新 更多