Deserialization of Arrays in XML response - c#

I'm still struggling with deserialization of XML containing arrays of items.
The response I want to deserialize:
<ns1:OperationResult xmlns:ns1="http://xxxx.com">
<done>false</done>
<errorEntities>
<elements>
<entityID>100014</entityID>
<entityType>GROUP</entityType>
<errors>
<errorCode>INVALID_DATA</errorCode>
<errorMessage>s: d3f62887-a2a3-4cde-8f8b-09812a7bd011ed8d385e-f4c4-4fae-9a4b-1ba405db54b6-MessageTemplate:{k2.constraints.numberFormat.length}|length:5|; </errorMessage>
</errors>
</elements>
</errorEntities>
</ns1:OperationResult>
And this is my corresponding class:
[XmlRootAttribute(Namespace = "http://xxxx.", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities")]
public ErrorEntities errorEntities { get; set; }
public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements")]
public List<ErrorElements> elements { get; } = new List<ErrorElements>();
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityId")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors")]
Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
I have already a method deserializing my responses. Actually I am struggling with this specific one. Alle others without arrays are working fine.
What I finally get is this:
Any advice is highly appreciated.

You have a few issues
1) The namespace in the xml and the classes have to be the same
2) The tags names in the classes are case sensitive so you have to make sure the spelling is correct (Upper/Lower Case)
3) The class object have to be public otherwise the tags are ignored.
4) Where there are no namespaces in XML (and parent has a namespace) you need the empty string for the namespaces
See corrected code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(GroupCreateUpdateResult));
GroupCreateUpdateResult group = (GroupCreateUpdateResult)serializer.Deserialize(reader);
}
}
[XmlRootAttribute(Namespace = "http://com.f24.soap.fwi.schema", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done", Namespace = "")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities", Namespace = "")]
public ErrorEntities errorEntities { get; set; }
//public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements", Namespace = "")]
public List<ErrorElements> elements { get; set;}
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityID")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors", Namespace = "")]
public Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
}

Related

XML deserialization to object

So i've been trying to deserialize this xml file to some objects, its simple enough but it keeps returning null to the objects, the data that i need is stored inside the attributes of the element.
Here is the XML.
<exchangerates xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="Valutakurser" author="Danmarks Nationalbank" refcur="DKK" refamt="1">
<dailyrates id="2020-10-20">
<currency code="AUD" desc="Australske dollar" rate="442,98"/>
<currency code="BGN" desc="Bulgarske lev" rate="380,53"/>
</dailyrates>
And this is the deserialisation code.
public static T DeserializeElement<T>(string filename)
{
try
{
T result;
XmlSerializer serializer = new XmlSerializer(typeof(T), new
XmlRootAttribute("exchangerates"));
using (TextReader tr = new StringReader(filename))
{
result = (T)serializer.Deserialize(tr);
}
return result;
}
catch { throw; }
}
And these are the objects
[XmlRoot(Namespace = "http://www.w3.org/2001/XMLSchema-instance",
ElementName = "exchangerates",
DataType = "Valutakurser")]
[Serializable]
public class Valutakurser
{
[XmlArray("dailyrates")]
public DateTime Id { get; set; }
public Currency Currency { get; set; }
}
[Serializable]
public class Currency
{
public string Code { get; set; }
public string Desc { get; set; }
public double Rate { get; set; }
public Currency() { }
}
Currently I keep getting this error and everything returned null:
InvalidOperationException: For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Valutakurser));
Valutakurser valutakurser = (Valutakurser)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "exchangerates")]
public class Valutakurser
{
[XmlAttribute]
public DateTime id { get; set; }
[XmlElement("dailyrates")]
public DailyRates DalyRates { get; set; }
}
public class DailyRates
{
[XmlElement("currency")]
public List<Currency> Currency { get; set; }
}
public class Currency
{
[XmlAttribute]
public string code { get; set; }
[XmlAttribute]
public string desc { get; set; }
[XmlAttribute]
public double rate { get; set; }
public Currency() { }
}
}

How to deserialize xml parent root attribute

I have following XML Structure:
<ComputationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" DataType="DimX">
<Mode Name="M1">
<Area>
<Point PointNumber="3" Speed="127" Power="1455" Value="-2" />
<Point PointNumber="2" Speed="127" Power="1396.8" Value="2" />
<Point PointNumber="3" Speed="101.6" Power="1164" Value="-2" />
</Area>
</Mode>
</ComputationData>
In below class structure I am not able to get the value of Datatype which is available in XMl root(ComputationData).
For following XML I have created following class structure:
[Serializable]
[XmlRoot("ComputationData")]
public class FullLoadPerformanceGrid
{
/// <summary>
/// Name of the performance data type of this grid, e.g. Bsfc, tEat...
/// </summary>
[XmlElement(ElementName = "ComputationData", Type =
typeof(PerformanceType))]
public PerformanceType DataType { get; set; }
/// <summary>
/// List of available <see cref="FullLoadPerformanceMode"/>
/// </summary>
[XmlElement("Mode", Type = typeof(FullLoadPerformanceMode))]
public List<FullLoadPerformanceMode> Modes { get; set; }
}
[Serializable]
[XmlRoot("ComputationData")]
public class PerformanceType
{
public int Id { get; set; }
[DataMember(Name = "DataType")]
[XmlAttribute("DataType")]
public string DataType { get; set; }
public int Type { get; set; }
}
Can anyone help me with the class structure that how should I define the PerformanceType(DataType)?
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(FullLoadPerformanceGrid));
FullLoadPerformanceGrid load = (FullLoadPerformanceGrid)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "ComputationData", Namespace = "")]
public class FullLoadPerformanceGrid
{
[XmlAttribute("DataType", Namespace = "")]
public string DataType { get; set; }
[XmlElement(ElementName = "Mode", Namespace = "")]
public Mode mode { get; set; }
}
[XmlRoot(ElementName = "Mode", Namespace = "" )]
public class Mode
{
[XmlAttribute("Name", Namespace = "")]
public string name { get; set; }
[XmlArray("Area", Namespace = "")]
[XmlArrayItem("Point", Namespace = "")]
public List<Point> points { get; set; }
}
[XmlRoot(ElementName = "Point", Namespace = "")]
public class Point
{
[XmlAttribute("PointNumber", Namespace = "")]
public int pointNumber { get; set; }
[XmlAttribute("Speed", Namespace = "")]
public decimal speed { get; set; }
[XmlAttribute("Power", Namespace = "")]
public decimal power { get; set; }
[XmlAttribute("Value", Namespace = "")]
public int value { get; set; }
}
}

Deserialize and get xml having 2 attributes with different ID

I want to Deserialize and get values of 2 attributes with different ID.
<Attributes><AddressAttribute ID="18"><AddressAttributeValue><Value>Sala 305</Value></AddressAttributeValue></AddressAttribute><AddressAttribute ID="17"><AddressAttributeValue><Value>3434</Value></AddressAttributeValue></AddressAttribute></Attributes>
I treid this C# code but it only returns the 1st attribute.
please help
[XmlRoot(ElementName = "AddressAttributeValue")]
public class AddressAttributeValue
{
[XmlElement(ElementName = "Value")]
public string Value { get; set; }
}
[XmlRoot(ElementName = "AddressAttribute")]
public class AddressAttribute
{
[XmlElement(ElementName = "AddressAttributeValue")]
public AddressAttributeValue AddressAttributeValue { get; set; }
[XmlAttribute(AttributeName = "ID")]
public string ID { get; set; }
}
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute AddressAttribute { get; set; }
}
var xmlData= customer.BillingAddress.CustomAttributes;
XmlSerializer serializer = new XmlSerializer(typeof(Attributes));
Attributes data;
using (TextReader reader = new StringReader(xmlData))
{
data = (Attributes)serializer.Deserialize(reader);
}
Should I change classes of Deserialize logic???
Sometimes using Linq instead of xml serialization can be simpler
var list = XDocument.Parse(xmlstring).Descendants("AddressAttribute")
.Select(x => new
{
Id = (int)x.Attribute("ID"),
Value = (string)x.Element("AddressAttributeValue").Element("Value")
})
.ToList();
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute AddressAttribute { get; set; }
}
Change it to:
[XmlRoot(ElementName = "Attributes")]
public class Attributes
{
[XmlElement(ElementName = "AddressAttribute")]
public AddressAttribute[] AddressAttribute { get; set; }
}
As you need to have collection of AddressAttribute you need to declare as an array.

How to Deserialize XML Array items?

I am having trouble deserializing XML. I get AccountInformation to work but it won't work with the Leauge elements. The XML doesn't contain any tag for "Leauges" and I don't want to add that tag to get it to work. Is there any other way to "fix" it? I have tried diffrent solutions but the deserialized result of the leauges comes back empty. What am I missing?
Any help appreciated!
Se my code below:
Update:
I have modified the code and the XML but I won't work anyway. What am I missing here?
[Serializable]
[XmlRoot(ElementName = "LeaugeCollection", Namespace = "")]
public class LeagueCollection
{
[XmlArray("Leagues")]
[XmlArrayItem("League",typeof(League))]
public League[] League { get; set; }
[XmlElement(ElementName = "AccountInformation")]
public string AccountInformation { get; set; }
}
[Serializable()]
public class League
{
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Country")]
public string Country { get; set; }
[XmlElement(ElementName = "Historical_Data")]
public string Historical_Data { get; set; }
[XmlElement(ElementName = "Fixtures")]
public string Fixtures { get; set; }
[XmlElement(ElementName = "LiveScore")]
public string Livescore { get; set; }
[XmlElement(ElementName = "NumberOfMatches")]
public int NumberOfMatches { get; set; }
[XmlElement(ElementName = "LatestMatch")]
public DateTime LatestMatch { get; set; }
}
Deserialize code:
public static void Main(string[] args)
{
XmlSerializer deserializer = new XmlSerializer(typeof(LeagueCollection));
TextReader reader = new StreamReader(#"C:\XmlFiles\XmlSoccer.xml");
object obj = deserializer.Deserialize(reader);
LeagueCollection XmlData = (LeagueCollection)obj;
reader.Close();
}
Link to XML:
Thanks in advance!
The XML you have in the image is missing the actual array element (Leauges), it has only the array items elements (Leauge), that is why you cannot get it deserialized!
UPDATE:
Ok, trying to reproduce your code, I now see that in your XML your elements are spelled "League" while in your code "Leauge"
FIX that first!
UPDATE2:
After the edits you have done according to my comments,it seems to work fine!
You are missing a namespace. I don't like both Leagues and League. Leagues is unnecessary.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
LeagueCollection leagueCollection = new LeagueCollection() {
leagues = new Leagues() {
League = new List<League>() {
new League() {
Id = 1,
Name = "English Premier League",
Country = "England",
Historical_Data = "Yes",
Fixtures = "Yes",
Livescore = "Yes",
NumberOfMatches = 5700,
LatestMatch = DateTime.Parse( "2015-05-24T16:00:00+00:00")
},
new League() {
Id = 2,
Name = "English League Championship",
Country = "England",
Historical_Data = "Yes",
Fixtures = "Yes",
Livescore = "Yes",
NumberOfMatches = 5700,
LatestMatch = DateTime.Parse("2015-05-24T16:00:00+00:00")
}
}
},
AccountInformation = "Confidential info"
};
XmlSerializer serializer = new XmlSerializer(typeof(LeagueCollection));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, leagueCollection);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer deserializer = new XmlSerializer(typeof(LeagueCollection));
XmlTextReader reader = new XmlTextReader(FILENAME);
LeagueCollection XmlData = (LeagueCollection)deserializer.Deserialize(reader);
reader.Close();
}
}
[XmlRoot(ElementName = "LeaugeCollection")]
public class LeagueCollection
{
[XmlElement("Leagues")]
public Leagues leagues { get; set; }
[XmlElement(ElementName = "AccountInformation")]
public string AccountInformation { get; set; }
}
[XmlRoot("Leagues")]
public class Leagues
{
[XmlElement("League")]
public List<League> League { get; set; }
}
[XmlRoot("League")]
public class League
{
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Country")]
public string Country { get; set; }
[XmlElement(ElementName = "Historical_Data")]
public string Historical_Data { get; set; }
[XmlElement(ElementName = "Fixtures")]
public string Fixtures { get; set; }
[XmlElement(ElementName = "LiveScore")]
public string Livescore { get; set; }
[XmlElement(ElementName = "NumberOfMatches")]
public int NumberOfMatches { get; set; }
[XmlElement(ElementName = "LatestMatch")]
public DateTime LatestMatch { get; set; }
}
}
​
​

How to extract data from xml with namespace?

Data ("1.0.0") from attribute "version" fall into property. But the property "Event" in the same class remains empty.
If cut namespace from XML, it will work.
My XML:
<rootnode>
<ns:eventresponse xmlns:ns="somenamespace" version="1.0.0">
<event id="694717028">
<somedata>val</somedata>
</event>
</ns:eventresponse>
</rootnode>
My class:
[XmlRoot("rootnode")]
public class RootNode
{
[XmlElement(ElementName = "eventresponse", Namespace = "somenamespace")]
public EventResponseData EventResponse { get; set; }
}
public class EventResponseData
{
[XmlElement("event")]
public EventData Event { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
}
public class TvEventData
{
[XmlAttribute("id")]
public string EventID { get; set; }
[XmlElement("somedata")]
public string SomeData { get; set; }
}
My Deserializer:
using (var reader = XmlReader.Create(new StringReader(xml)))
{
reader.MoveToContent();
var obj = (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
Your event element is implicitly in the same namespace in the XML due to namespace defaulting, so you should specify that in your declaration:
public class EventResponseData
{
[XmlElement(ElementName = "event", Namespace = "somenamespace")]
public EventData Event { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
}

Categories

Resources