Home > Net >  XML parse to object, get invalid operation exception
XML parse to object, get invalid operation exception

Time:12-22

I trying to add extension method for Flurl that parse http response from xml to object. There is code

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

But when I trying to parse this 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>

I got the an error

System.InvalidOperationException: <Service.ABC xmlns='http://schemas.datacontract.org/2004/07/Services.Public'> was not expected.

the model I build is from

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

If use XmlDocument and load this xml file could be parse successfully, So... I think the file is correct. But What's the problem in XmlSerializer?

CodePudding user response:

The site you used doesn't seem reliable. Did you notice it gave you 3 XmlRoot classes?

Using the Paste XML as classes feature in Visual Studio this is what I get:

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

CodePudding user response:

You are missing the namespace declaration on your root object ServiceABC.

You also appear to have incorrect nested objects: nil="true" just means it's a nullable field. I'd have to guess what the real types are due to lack of information.

[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

  • Related