Deserialize and get xml having 2 attributes with different ID - c#

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.

Related

How can i bind xml element with C# model when xml have multiple Same Element?

I cannot bind my c# model with this kind of xml file. Because there is multiple element with same.
This is a example of my XML File.
<Type>
<Loop LoopId="2100A" Name="MEMBER NAME">
<PER>
<!--Contact Function Code-->
<PER01>IP<!--Insured Party--></PER01>
<PER02 />
<!--Communication Number Qualifier-->
<PER03>HP<!--Home Phone Number--></PER03>
<!--Communication Number-->
<PER04>6235834409</PER04>
</PER>
</Loop>
<Loop LoopId="2100C" Name="MEMBER MAILING ADDRESS">
<NM1>
<!--Entity Identifier Code-->
<NM101>31<!--Postal Mailing Address--></NM101>
<!--Entity Type Qualifier-->
<NM102>1<!--Person--></NM102>
</NM1>
</Loop>
<Loop LoopId="2100G" Name="RESPONSIBLE PERSON">
<PER>
<!--Contact Function Code-->
<PER01>IP<!--Insured Party--></PER01>
<PER02 />
<!--Communication Number Qualifier-->
<PER03>HP<!--Home Phone Number--></PER03>
<!--Communication Number-->
<PER04>6235834409</PER04>
</PER>
<LM>
<!--Contact Function Code-->
<LM01>RP<!--Responsible Person--></LM01>
<LM02 />
</LM>
</Loop>
</Type>
I have use this following code to bind. But Code is not working, cause data binding get confused.
[XmlElement(ElementName = "Loop")]
public L3_L1_MemberName L3_L1_MemberName { get; set; }
[XmlElement(ElementName = "Loop")]
public L3_L2_MemberMailingAddress L3_L2_MemberMailingAddress { get; set; }
[XmlElement(ElementName = "Loop")]
public L3_L3_ResponsiblePerson L3_L3_ResponsiblePerson { get; set; }
based your XML, the model looks like
[XmlRoot(ElementName = "PER")]
public class PER
{
[XmlElement(ElementName = "PER01")]
public string PER01 { get; set; }
[XmlElement(ElementName = "PER02")]
public string PER02 { get; set; }
[XmlElement(ElementName = "PER03")]
public string PER03 { get; set; }
[XmlElement(ElementName = "PER04")]
public string PER04 { get; set; }
}
[XmlRoot(ElementName = "Loop")]
public class Loop
{
[XmlElement(ElementName = "PER")]
public PER PER { get; set; }
[XmlAttribute(AttributeName = "LoopId")]
public string LoopId { get; set; }
[XmlAttribute(AttributeName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "NM1")]
public NM1 NM1 { get; set; }
[XmlElement(ElementName = "LM")]
public LM LM { get; set; }
}
[XmlRoot(ElementName = "NM1")]
public class NM1
{
[XmlElement(ElementName = "NM101")]
public string NM101 { get; set; }
[XmlElement(ElementName = "NM102")]
public string NM102 { get; set; }
}
[XmlRoot(ElementName = "LM")]
public class LM
{
[XmlElement(ElementName = "LM01")]
public string LM01 { get; set; }
[XmlElement(ElementName = "LM02")]
public string LM02 { get; set; }
}
[XmlRoot(ElementName = "Type")]
public class Type
{
[XmlElement(ElementName = "Loop")]
public List<Loop> Loop { get; set; }
}
Here is the logic to DeSerialize the XML to Object
XmlSerializer serializer = new XmlSerializer(typeof(Type));
string xml = File.ReadAllText("XMLFile3.xml");
using (TextReader reader = new StringReader(xml))
{
var results = (Type)serializer.Deserialize(reader);
foreach (var item in results.Loop)
{
Console.WriteLine($"{item.LoopId} {item.Name}");
if (item.PER != null)
{
Console.WriteLine($"PER:{Regex.Replace(item.PER.PER01, #"\s+", "")}-{Regex.Replace(item.PER.PER02, #"\s+", "")}-{Regex.Replace(item.PER.PER03, #"\s+", "")}-{Regex.Replace(item.PER.PER04, #"\s+", "")}");
}
if (item.NM1 != null)
{
Console.WriteLine($"NM1:{Regex.Replace(item.NM1.NM101, #"\s+", "")}-{Regex.Replace(item.NM1.NM102, #"\s+", "")}");
}
if (item.LM != null)
{
Console.WriteLine($"LM:{Regex.Replace(item.LM.LM01, #"\s+", "")}-{Regex.Replace(item.LM.LM02, #"\s+", "")}");
}
}
}
OUTPUT
2100A MEMBER NAME
PER:IP--HP-6235834409
2100C MEMBER MAILING ADDRESS
NM1:31-1
2100G RESPONSIBLE PERSON
PER:IP--HP-6235834409
LM:RP-

Deserialization of Arrays in XML response

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

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 Serialize Nested Classes and Collections into XML?

First, i tried on the internet different ways, but i didn't got what i want. i have viewmodel class with the following properties;
public class UserEntitySubmissionsReportViewModel
{
public UserEntitySubmissionsReportViewModel()
{
Submissions = new FinalUserEntitiesAssignmentViewModel();
}
public int Id { get; set; }
public int Status { get; set; }
public DateTime SubmissionDate { get; set; }
public int UserEntityAssignmentId { get; set; }
public FinalUserEntitiesAssignmentViewModel Submissions { get; set; }
}
and the nested class FinalUserEntitiesAssignmentViewModel whcih is;
[Serializable]
public class FinalUserEntitiesAssignmentViewModel
{
public FinalUserEntitiesAssignmentViewModel()
{
ProjectInformation = new ProjectInformationViewModel();
MilestoneInformation = new MilestoneInformationViewModel();
ActivityListInformation = new ActivityListInformationViewModel();
ActivityInformation = new ActivityInformationViewModel();
SubActivityInformation = new List<SubActivityInformationViewModel>();
}
[XmlElement(ElementName = "ProjectInformation")]
public ProjectInformationViewModel ProjectInformation { get; set; }
[XmlElement(ElementName = "MilestoneInformation")]
public MilestoneInformationViewModel MilestoneInformation { get; set; }
[XmlElement(ElementName = "ActivityListInformation")]
public ActivityListInformationViewModel ActivityListInformation { get; set; }
[XmlElement(ElementName = "ActivityInformation")]
public ActivityInformationViewModel ActivityInformation { get; set; }
[XmlElement(ElementName = "SubActivityInformation")]
public List<SubActivityInformationViewModel> SubActivityInformation { get; set; }
}
[Serializable]
public class ProjectInformationViewModel
{
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
public string Description { get; set; }
}
When i serialize this, i only get the 1 property i.e Id for nested class.
var obj = new UserEntitySubmissionsReportViewModel();
var writer = new System.Xml.Serialization.XmlSerializer(typeof(UserEntitySubmissionsReportViewModel));
System.IO.StreamWriter file = new System.IO.StreamWriter(Server.MapPath("~/App_Data/UserEntitySubmissionsReportViewModel.xml"));
writer.Serialize(file, obj);
file.Close();
The result i get is;
<?xml version="1.0" encoding="utf-8"?>
<UserEntitySubmissionsReportViewModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>0</Id>
<Status>0</Status>
<SubmissionDate>0001-01-01T00:00:00</SubmissionDate>
<UserEntityAssignmentId>0</UserEntityAssignmentId>
<Submissions>
<ProjectInformation>
<Id>0</Id>
</ProjectInformation>
<MilestoneInformation>
<Id>0</Id>
</MilestoneInformation>
<ActivityListInformation>
<Id>0</Id>
</ActivityListInformation>
<ActivityInformation>
<Id>0</Id>
<Attributes />
<Tools />
</ActivityInformation>
</Submissions>
</UserEntitySubmissionsReportViewModel>
As you can see, i am not able to serialize other properties. Similarly i have nest collection too. How can i serialize nested properties using C# ?
I think that when serializing XML that you need to define a default constructor for your classes. Try adding a construction for your ProjectInformationViewModel class.
public class ProjectInformationViewModel
{
// Default Constructor
public ProjectInformationViewModel()
{
}
}

Deserializing a List of KeyValuePairs

I have some XML in the following format:
<ObjectData>
<ModelName>MODEL_123</ModelName>
<ObjectName>OBJECT_A</ObjectName>
<Values>
<KeyValuePair>
<Key>NAME</Key>
<Value>PAUL</Value>
</KeyValuePair>
...
</Values>
</ObjectData>
...
I want to deserialize this into the following class:
[XmlRoot(Namespace = "")]
public class ObjectData
{
[XmlElement(Namespace = "")]
public string ModelName { get; set; }
[XmlElement(Namespace = "")]
public string ObjectName { get; set; }
[XmlArray]
public List<KeyValuePair<string, string>> Values { get; set; }
}
When I use this code, the KeyValuePairs are not deserialized and the Values property is empty.
List<ObjectData> data = new List<ObjectData>();
XmlSerializer serializer = new XmlSerializer(typeof(ObjectData));
using (XmlReader reader = XmlReader.Create(new StringReader(inputXML)))
{
reader.MoveToContent();
ObjectData temp = (ObjectData)serializer.Deserialize(reader);
data.Add(temp);
}
Is the KeyValuePair class not serializable in the way I use it? Or is there a problem in my ObjectData class?
Try specifying the element names in your attributes:
[XmlArray("Values")]
[XmlArrayItem("KeyValuePair")]
public List<KeyValuePair<string, string>> Values { get; set; }
Combining D Stanley's answer with this post, I was able to come up with the right structure:
[XmlRoot(Namespace = "")]
public class ObjectData
{
[XmlElement(Namespace = "")]
public string ModelName { get; set; }
[XmlElement(Namespace = "")]
public string ObjectName { get; set; }
[XmlArray("Values")]
[XmlArrayItem("KeyValuePair")]
public List<KeyValuePair<string, string>> Values { get; set; }
}
[Serializable]
public class KeyValuePair<K, V> {
public K Key { get; set; }
public V Value { get; set; }
public KeyValuePair() { }
public KeyValuePair(K key, V value)
{
this.Key = key;
this.Value = value;
}
}
There is no setter for Key or Value in the KeyValuePair struct. You'll have to change the data type. You can decorate the property so you can name the new type whatever you want.
....
[XmlArray("Values")]
[XmlArrayItem("KeyValuePair")] //not needed if MyItem is named KeyValuePair
public List<MyItem> Values { get; set; }
}
public class MyItem
{
public string Key { get; set; }
public string Value { get; set; }
}

Categories

Resources