I have the following XML Scenario:
<al2:Dispatch xmlns:al1="al:1.0.0" xmlns:al2="al:2.0.0">
<al2:MsgIdentificator>0001</al2:MsgIdentificator>
..
<al1:DispatchReceiverGroup>
<al2:Receiver>
<al1:ANumberIdentificator>100001</al1:ANumberIdentificator>
<al1:BNumberIdentificator>1000000001</al1:BNumberIdentificator>
</al2:Receiver>
</al1:DispatchReceiverGroup>
</al2:Dispatch>
So My Model is as follows:
[Serializable]
[XmlRoot(Namespace = "al:2.0.0", ElementName = "Dispatch")]
public class BatchDistribution
{
[XmlElement(Namespace = "al:2.0.0", ElementName = "MsgIdentificator")]
public string MessageIdentificator { get; set; }
//CONFUSED HERE
[XmlArray(Namespace = "al:1.0.0", ElementName = "DispatchReceiverGroup")]
[XmlArrayItem(Namespace = "al:2.0.0", ElementName = "Receiver")]
public List<DistributionReceiver> DistributionRecievers { get; set; }
}
}
So I want to have an optional amount of Elements of ANumberIdentificator and BNumberIdentificator elements. For this, I made a Base Class DistributionReceiver, which is inherited by DistributionReceiverA and DistributionReceiverB, such as follows:
[Serializable]
public class DistributionReceiver
{
[XmlElement(Namespace = "al:1.0.0")] //note i dont assign value for Element name because it has to be decided by sub classes
public string NumberIdentificator{ get; set; }
}
and the sub classes:
[Serializable]
public class DistributionRecieverA : DistributionReceiver
{
[XmlElement(Namespace = "al:1.0.0", ElementName = "ANumberIdentificator")]
public new string ANumberIdentificator { get; set; }
}
and the other
[Serializable]
public class DistributionRecieverB : DistributionReceiver
{
[XmlElement(Namespace = "al:1.0.0", ElementName = "BNumberIdentificator")]
public new string BNumberIdentificator { get; set; }
}
Problem is: I don't get serialized ANumberIdentificator and BNumberIdentificator.
Looks like the model is incorrect for ANumberIdentificator and BNumberIdentificator
I have used xmltocsharp to convert the example XML and the model looked like
[XmlRoot(ElementName = "Receiver", Namespace = "al:2.0.0")]
public class Receiver
{
[XmlElement(ElementName = "ANumberIdentificator", Namespace = "al:1.0.0")]
public List<string> ANumberIdentificator { get; set; }
[XmlElement(ElementName = "BNumberIdentificator", Namespace = "al:1.0.0")]
public List<string> BNumberIdentificator { get; set; }
}
[XmlRoot(ElementName = "DispatchReceiverGroup", Namespace = "al:1.0.0")]
public class DispatchReceiverGroup
{
[XmlElement(ElementName = "Receiver", Namespace = "al:2.0.0")]
public Receiver Receiver { get; set; }
}
[XmlRoot(ElementName = "Dispatch", Namespace = "al:2.0.0")]
public class Dispatch
{
[XmlElement(ElementName = "MsgIdentificator", Namespace = "al:2.0.0")]
public string MsgIdentificator { get; set; }
[XmlElement(ElementName = "DispatchReceiverGroup", Namespace = "al:1.0.0")]
public DispatchReceiverGroup DispatchReceiverGroup { get; set; }
[XmlAttribute(AttributeName = "al1", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Al1 { get; set; }
[XmlAttribute(AttributeName = "al2", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Al2 { get; set; }
}
I have used XmlSerializer to convert the XML to object
XmlSerializer serializer = new XmlSerializer(typeof(Dispatch));
using (TextReader reader = new StringReader(xmlstring))
{
//convert the xml to object
Dispatch result = (Dispatch)serializer.Deserialize(reader);
}
And I am able to read A and B under Receiver
Console.WriteLine(result.DispatchReceiverGroup.Receiver.ANumberIdentificator);
Console.WriteLine(result.DispatchReceiverGroup.Receiver.BNumberIdentificator);
The XmlArrayItem must enumerate all possible types in your array
XmlArrayItem(ElementName="DistributionReceiver", Type=typeof(DistributionReciever)),
XmlArrayItem(ElementName="DistributionRecieverA", Type=typeof(DistributionRecieverA)),
XmlArrayItem(ElementName="DistributionRecieverB", Type=typeof(DistributionRecieverB)),
The serializer need to conclude, from ElementName to Runtime-Type. (add your namespace yourself). The place of XmlArrayItem is correct, but add multiple !
If your base-class is abstract, do not create an XmlArrayItem for it.
Related
I've been given an xml containing two elements that have the same namem, 'Log', but where each 'Log' element has different attribute names. E.g. the first 'Log' element has attribute name 'AttrA' and the second 'Log' element has 'AttrB'. I've tried using XmlArrayItem, but don't get it to read in the array. In the code below, the 'myObjectWithoutLog' object contains Elm, but not the Log data. Anybody know how I can get the two Log elements into the serialized object?
XML
<Elm DbLocation="C:\Data\Db\My.db">
<Log AttrA="C:\Data\Log\Log1.csv"/>
<Log AttrA="C:\Data\Log\Log2.csv"/>
</Elm>
C#
[XmlRoot(ElementName = "Elm", Namespace = "")]
public class myXmlObject
{
public myXmlObject()
{
}
[XmlAttribute("DbLocation", Namespace = "")]
public string DbLocation { get; set; }
[XmlArrayItem("Log", Namespace = "")]
public List<Log> logs { get; set; }
}
[XmlRoot(ElementName = "Log", Namespace = "")]
public class Log
{
[XmlAttribute("AttrA", Namespace = "")]
public string attrA { get; set; }
[XmlAttribute("AttrB", Namespace = "")]
public string attrB { get; set; }
}
public class RunIt
{
XmlSerializer serializer = new XmlSerializer(typeof(myXmlObject));
using (FileStream stream = new FileStream(myXmlFile, FileMode.Open))
{
myXmlObject myObjectWithoutLog = (myXmlObject)serializer.Deserialize(stream);
}
}
You're using wrong Xml attribute. You need to use XmlElement instead of XmlArrayItem.
[XmlRoot(ElementName = "Elm", Namespace = "")]
public class myXmlObject
{
public myXmlObject()
{
}
[XmlAttribute("DbLocation", Namespace = "")]
public string DbLocation { get; set; }
[XmlElement("Log", Namespace = "")]
public List<Log> logs { get; set; }
}
[XmlRoot(ElementName = "Log", Namespace = "")]
public class Log
{
[XmlAttribute("AttrA", Namespace = "")]
public string attrA { get; set; }
[XmlAttribute("AttrB", Namespace = "")]
public string attrB { get; set; }
}
I'm using the XmlSerializer in System.Xml.Serialization.
I have a list (or two lists really) separated by xsi:type.
<?xml version="1.0" encoding="utf-8"?>
<ButikerOmbud xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Info>
<Meddelande>blah blah</Meddelande>
</Info>
<ButikOmbud xsi:type="StoreAssortmentViewModel">
<Typ>Butik</Typ><Nr>2515</Nr>
</ButikOmbud>
<ButikOmbud xsi:type="StoreAssortmentViewModel">
<Typ>Butik</Typ><Nr>2516</Nr>
</ButikOmbud>
<ButikOmbud xsi:type="AgentAssortmentViewModel">
<Typ>Ombud</Typ><Nr>011703-91A</Nr>
</ButikOmbud>
<ButikOmbud xsi:type="AgentAssortmentViewModel">
<Typ>Ombud</Typ><Nr>011703-92B</Nr>
</ButikOmbud>
</ButikerOmbud>
I've created some classes that map to this:
[XmlRoot(ElementName = "ButikerOmbud")]
public class ButiksCollection
{
[XmlElement(ElementName = "Info")]
public Info Info { get; set; }
[XmlElement(ElementName = "ButikOmbud")]
public List<Butik> Butiker { get; set; }
}
[XmlRoot(ElementName = "ButikOmbud")]
[XmlType(TypeName = "StoreAssortmentViewModel")]
public class Butik
{
[XmlElement(ElementName = "Typ")]
public string Typ { get; set; }
[XmlElement(ElementName = "Nr")]
public int Nr { get; set; }
}
and then I'll do this
(ButiksCollection)(new XmlSerializer(typeof(ButiksCollection)).Deserialize(memoryStream));
This should work if only the StoreAssortmentViewModel existed. But given that there exists AgentAssortmentViewModel under the same node. I'm not sure how I should de-serialise this. I'm assuming there should be another collection List<Butik> Agents on ButiksCollection.
The only attribute I've found that seems to map to xsi:type is applied to classes, which I don't think is what I want here
How do I arrange and attribute my classes so this will de-serialize?
Here's all that on dotnetfiddle: https://dotnetfiddle.net/vmT4SK
Try following :
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(ButiksCollection));
ButiksCollection butik = (ButiksCollection)serializer.Deserialize(reader);
List<StoreAssortmentViewModel> storeAssortments = butik.Butiker.Where(x => x.GetType() == typeof(StoreAssortmentViewModel)).Select(x => (StoreAssortmentViewModel)x).ToList();
List<AgentAssortmentViewModel> agentAssortments = butik.Butiker.Where(x => x.GetType() == typeof(AgentAssortmentViewModel)).Select(x => (AgentAssortmentViewModel)x).ToList();
}
}
[XmlRoot(ElementName = "ButikerOmbud")]
public class ButiksCollection
{
[XmlElement(ElementName = "Info")]
public Info Info { get; set; }
[XmlElement(ElementName = "ButikOmbud")]
public List<Butik> Butiker { get; set; }
}
[XmlRoot(ElementName = "ButikOmbud")]
[XmlInclude(typeof(StoreAssortmentViewModel))]
[XmlInclude(typeof(AgentAssortmentViewModel))]
public class Butik
{
[XmlElement(ElementName = "Typ")]
public string Typ { get; set; }
[XmlElement(ElementName = "Nr")]
public string Nr { get; set; }
}
public class Info
{
public string Meddelande { get; set; }
}
public class StoreAssortmentViewModel : Butik
{
}
public class AgentAssortmentViewModel : Butik
{
}
}
I'm trying to deserialize the following xml document into a C# object:
<ns1:StockerFichiers
xmlns:ns1="http://www.foo.fr/bar/Repository"
xmlns:ns0="http://www.foo.fr/bar/Transport/">
<ns1:fichiersAStocker>
<ns0:FichierIdentifie>
<ns0:Contenu></ns0:Contenu>
<ns0:DomaineIdLocalDoc>128</ns0:DomaineIdLocalDoc>
<ns0:EstOriginal>true</ns0:EstOriginal>
<ns0:IdLocalDoc>2018-07-06T154554_70183_2</ns0:IdLocalDoc>
<ns0:PieceDynamique>false</ns0:PieceDynamique>
<ns0:GoldenSource>false</ns0:GoldenSource>
<ns0:TypeDoc>PDF</ns0:TypeDoc>
<ns0:TypeMime>application/pdf</ns0:TypeMime>
</ns0:FichierIdentifie>
</ns1:fichiersAStocker>
</ns1:StockerFichiers>
I know a lot of deserialization questions already exist, but even if some seems to be solving the same issue I face, None of what I've tried did populate my List<FichierIdentifie>.
Where I deserialize:
public void StockerFichiersXmlBase64(string fichiersAStocker)
{
//serializer
XmlRootAttribute xroot = new XmlRootAttribute();
xroot.ElementName = "StockerFichiers";
xroot.Namespace = NamespacesConstantes.NAMESPACE_SWREPOSITORY; //ns1
XmlSerializer deserializer = new XmlSerializer(typeof(StockerFichiersRoot),xroot );
//fichiersAStocker is base64 encoded
byte[] data = Convert.FromBase64String(fichiersAStocker);
StringReader stringReader = new StringReader(Encoding.UTF8.GetString(data));
//deserialization
StockerFichiersRoot deserializedFiles = (StockerFichiersRoot)deserializer.Deserialize(stringReader);
}
My current version :
// Root
[XmlRoot(ElementName = "StockerFichiers", Namespace = NamespacesConstantes.NAMESPACE_SWREPOSITORY)]
public class StockerFichiersRoot
{
[XmlElement(ElementName = "fichiersAStocker", Namespace = NamespacesConstantes.NAMESPACE_SWREPOSITORY)]
public FichiersAStocker fichiersAStocker { get; set; }
}
//sub root
public class FichiersAStocker
{
[XmlArray(ElementName = "fichiersAStocker", Namespace = NamespacesConstantes.NAMESPACE_SWREPOSITORY)]
[XmlArrayItem(ElementName = "FichierIdentifie", Namespace=NamespacesConstantes.NAMESPACE_MSS_TRANSPORT)]
public List<FichierIdentifie> FichiersIdentifie { get; set; }
}
public class FichierIdentifie
{
[XmlElement(Namespace = NamespacesConstantes.NAMESPACE_TRANSPORT)]
public byte[] Contenu { get; set; }
//all fields are similar to the first one
}
And with this variation of the subroot class according to Is it possible to deserialize XML into List<T>? :
//sub root
public class FichiersAStocker
{
[XmlElement(ElementName = "FichierIdentifie", Namespace=NamespacesConstantes.NAMESPACE_MSS_TRANSPORT)]
public List<FichierIdentifie> FichiersIdentifie { get; set; }
}
I've also tried to remove the class FichiersAStocker (the sub root), to put the List<FichierIdentifie> in the root class, with both [xmlArray..] and [XmlElement] variations but with no success.
I always get an object with the list empty.
Try using XML2CSharp to generate class. Then try using that class or use it for debugging.
Generated code for your XML looks like this:
(You can remove unwanted properties)
/*
Licensed under the Apache License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0
*/
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName="FichierIdentifie", Namespace="http://www.foo.fr/bar/Transport/")]
public class FichierIdentifie {
[XmlElement(ElementName="Contenu", Namespace="http://www.foo.fr/bar/Transport/")]
public string Contenu { get; set; }
[XmlElement(ElementName="DomaineIdLocalDoc", Namespace="http://www.foo.fr/bar/Transport/")]
public string DomaineIdLocalDoc { get; set; }
[XmlElement(ElementName="EstOriginal", Namespace="http://www.foo.fr/bar/Transport/")]
public string EstOriginal { get; set; }
[XmlElement(ElementName="IdLocalDoc", Namespace="http://www.foo.fr/bar/Transport/")]
public string IdLocalDoc { get; set; }
[XmlElement(ElementName="PieceDynamique", Namespace="http://www.foo.fr/bar/Transport/")]
public string PieceDynamique { get; set; }
[XmlElement(ElementName="SisraGoldenSource", Namespace="http://www.foo.fr/bar/Transport/")]
public string SisraGoldenSource { get; set; }
[XmlElement(ElementName="TypeDocSisra", Namespace="http://www.foo.fr/bar/Transport/")]
public string TypeDocSisra { get; set; }
[XmlElement(ElementName="TypeMime", Namespace="http://www.foo.fr/bar/Transport/")]
public string TypeMime { get; set; }
}
[XmlRoot(ElementName="fichiersAStocker", Namespace="http://www.foo.fr/bar/Repository")]
public class FichiersAStocker {
[XmlElement(ElementName="FichierIdentifie", Namespace="http://www.foo.fr/bar/Transport/")]
public FichierIdentifie FichierIdentifie { get; set; }
}
[XmlRoot(ElementName="StockerFichiers", Namespace="http://www.foo.fr/bar/Repository")]
public class StockerFichiers {
[XmlElement(ElementName="fichiersAStocker", Namespace="http://www.foo.fr/bar/Repository")]
public FichiersAStocker FichiersAStocker { get; set; }
[XmlAttribute(AttributeName="ns1", Namespace="http://www.w3.org/2000/xmlns/")]
public string Ns1 { get; set; }
[XmlAttribute(AttributeName="ns0", Namespace="http://www.w3.org/2000/xmlns/")]
public string Ns0 { get; set; }
}
}
Really frustrating mistake that took me half a day to solve :
notice how "NamespacesConstantes.NAMESPACE_MSS_TRANSPORT" is close to "NamespacesConstantes.NAMESPACE_TRANSPORT". Add some lazy autocompletion and you can fool yourself while defining the [XmlElement...] in the "FichiersAStocker" class.
Thanks for your help Matt, I noticed this mistake while i paste some of my code on https://dotnetfiddle.net/ ! :)
I have two XML files, I am able to get data through xPath in c# from first XML which here:
<CONSOLIDATED_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://www.example/acb.xsd"
dateGenerated="2018-04-19T19:18:41.129-04:00">
<INDIVIDUALS>
<INDIVIDUAL>
<DATAID>2975591</DATAID>
<VERSIONNUM>1</VERSIONNUM>
<FIRST_NAME>ABC</FIRST_NAME>
<SECOND_NAME>XYZ</SECOND_NAME>
<INDIVIDUAL_ALIAS>
<QUALITY>Good</QUALITY>
<ALIAS_NAME>abcd</ALIAS_NAME>
</INDIVIDUAL_ALIAS>
<INDIVIDUAL_ALIAS>
<QUALITY>Bad</QUALITY>
<ALIAS_NAME>ylmn</ALIAS_NAME>
</INDIVIDUAL_ALIAS>
</INDIVIDUAL>
</INDIVIDUALS>
</CONSOLIDATED_LIST>
the way I am getting Data, please also see the comments inside code.
var xml = DownloadString(link); //link refers to XML file on web
e = XElement.Parse(xml);
//parentNodeForPerson = "INDIVIDUAL" for above and "sdnEntry" for below;
var lstIndividuals = e.Descendants(parentNodeForPerson);
Data _individualData;
List<Data> individualList = new List<Data>();
foreach (var individual in lstIndividuals)
{
_individualData = new Data();
//personParentValue1 for above is FIRST_NAME and below is firstName
_individualData.First_Name = individual.Descendants(personParentValue1)
.Any() == true ? individual.Descendants(personParentValue1).First().Value : "";
//personParentValue2 for above is SECOND_NAME and below is lastName
_individualData.Last_Name = individual.Descendants(personParentValue2)
.Any() == true ? individual.Descendants(personParentValue2).First().Value : "";
//childNodeForPersonfor above is INDIVIDUAL_ALIAS and below is aka
var lstIndvidualAlias = individual.Descendants(childNodeForPerson);
_individualData.Alias = new List<string>();
foreach (var alias in lstIndvidualAlias)
{
//personChildValue1 for above is ALIAS_NAME and below is lastName & fisrtName
if (!String.IsNullOrWhiteSpace(alias.Descendants(personChildValue1).First().Value))
{
_individualData.Alias.Add(alias.Descendants(personChildValue1)
.Any() == true ? alias.Descendants(personChildValue1).First().Value : "");
}
}
individualList.Add(_individualData);
}
this is XML where I am not getting data
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/List.xsd">
<publshInformation>
<Publish_Date>04/18/2018</Publish_Date>
<Record_Count>6299</Record_Count>
</publshInformation>
<sdnEntry>
<lastName>ABCD</lastName>
<fisrtName>XYS</fisrtName>
<akaList>
<aka>
<category>strong</category>
<lastName>ABCDT</lastName>
<fisrtName>XYS</fisrtName>
</aka>
<aka>
<category>Weak</category>
<lastName>AssDT</lastName>
<fisrtName>XYsS</fisrtName>
</aka>
</akaList>
</sdnEntry>
</List>
Edit:
Data Class
public class Data
{
public string Last_Name { get; set; }
public string First_Name { get; set; }
public List<string> Alias { get; set; }
}
SOLUTION
Yes, that's normal and depends on namespaces.
Just edit your LINQ queries and go from the one you used:
var lstIndividuals = e.Descendants(parentNodeForPerson);
to this:
var lstIndividuals = e.Descendants().Where(f => f.Name.LocalName.ToString() == parentNodeForPerson);
And it will work.
LONG EXPLANATION
The above solution basically ignores all namespace information when retrieving elements by name.
The things is that in the first XML you have:
<CONSOLIDATED_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://www.example/acb.xsd"
dateGenerated="2018-04-19T19:18:41.129-04:00">
Whilst in the second we find
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/List.xsd">
The second XML has two namespaces defined, which throws your LINQ queries out of whack; in fact, if you just removed this from the second XML
xmlns="http://tempuri.org/List.xsd"
your code would work without any changes.
To start with, you can read the answers to What does “xmlns” in XML mean?, especially this one. In short, namespaces can be useful e.g. when you combine XMLs from different sources and you get elements with the same name: by prepending a namespace, elements with the same name will be seen as different:
<namespaceA:elementName>blah </namespaceA:elementName>
<namespaceB:elementName>blah blah</namespaceB:elementName>
In your XML you have two namespaces but, when looking for Descendants you don't specify which namespace your elements belong to.
Another solution, perhaps more robust than the quick one above, would be specifying the namespace the name of an element belongs to, e.g. like the OP does in this question, using XName.Get: in your case, you would get the nodes of the second XML this way:
var lstIndividuals = e.Descendants(XName.Get(parentNodeForPerson, "http://tempuri.org/List.xsd"));
which works because the URI specified (http://tempuri.org/List.xsd) is the one of the default namespace you declared:
xmlns="http://tempuri.org/List.xsd"
and, since your elements don't have any prefix, it's the namespace your elements belong to; if they belonged to the other namespace you defined, i.e. xsi, their names would be e.g. xsi:sdnEntry.
Of course, since there's no default namespace in your first XML declaration but only the xsi namespace (which refers to a different URI), you would need to pass its URI to XName.Get and adapt your code.
In other words, you should make the URL parametric and pass it to your method, rather than hardcoding it like I did.
I tried your xml(s). I have used xml deserializer and it seems to work fine at my end. Please check the following code:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using XML1;
using XML2;
namespace ConsoleApplication1
{
public class Program
{
private static void Main(string[] args)
{
var list1 = Deserialize<CONSOLIDATED_LIST>(#"CONSOLIDATED_LIST.xml"); // pass the path to your xml here
var list2 = Deserialize<List>(#"LIST.xml");
}
public static T Deserialize<T>(string path)
{
T obj;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var reader = new StreamReader(path);
obj = (T)serializer.Deserialize(reader);
reader.Close();
return obj;
}
}
}
namespace XML1
{
[XmlRoot(ElementName = "INDIVIDUAL_ALIAS")]
public class INDIVIDUAL_ALIAS
{
[XmlElement(ElementName = "QUALITY")]
public string QUALITY { get; set; }
[XmlElement(ElementName = "ALIAS_NAME")]
public string ALIAS_NAME { get; set; }
}
[XmlRoot(ElementName = "INDIVIDUAL")]
public class INDIVIDUAL
{
[XmlElement(ElementName = "DATAID")]
public string DATAID { get; set; }
[XmlElement(ElementName = "VERSIONNUM")]
public string VERSIONNUM { get; set; }
[XmlElement(ElementName = "FIRST_NAME")]
public string FIRST_NAME { get; set; }
[XmlElement(ElementName = "SECOND_NAME")]
public string SECOND_NAME { get; set; }
[XmlElement(ElementName = "INDIVIDUAL_ALIAS")]
public List<INDIVIDUAL_ALIAS> INDIVIDUAL_ALIAS { get; set; }
}
[XmlRoot(ElementName = "INDIVIDUALS")]
public class INDIVIDUALS
{
[XmlElement(ElementName = "INDIVIDUAL")]
public INDIVIDUAL INDIVIDUAL { get; set; }
}
[XmlRoot(ElementName = "CONSOLIDATED_LIST")]
public class CONSOLIDATED_LIST
{
[XmlElement(ElementName = "INDIVIDUALS")]
public INDIVIDUALS INDIVIDUALS { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "noNamespaceSchemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string NoNamespaceSchemaLocation { get; set; }
[XmlAttribute(AttributeName = "dateGenerated")]
public string DateGenerated { get; set; }
}
}
namespace XML2
{
[XmlRoot(ElementName = "publshInformation", Namespace = "http://tempuri.org/List.xsd")]
public class PublshInformation
{
[XmlElement(ElementName = "Publish_Date", Namespace = "http://tempuri.org/List.xsd")]
public string Publish_Date { get; set; }
[XmlElement(ElementName = "Record_Count", Namespace = "http://tempuri.org/List.xsd")]
public string Record_Count { get; set; }
}
[XmlRoot(ElementName = "aka", Namespace = "http://tempuri.org/List.xsd")]
public class Aka
{
[XmlElement(ElementName = "category", Namespace = "http://tempuri.org/List.xsd")]
public string Category { get; set; }
[XmlElement(ElementName = "lastName", Namespace = "http://tempuri.org/List.xsd")]
public string LastName { get; set; }
[XmlElement(ElementName = "fisrtName", Namespace = "http://tempuri.org/List.xsd")]
public string FisrtName { get; set; }
}
[XmlRoot(ElementName = "akaList", Namespace = "http://tempuri.org/List.xsd")]
public class AkaList
{
[XmlElement(ElementName = "aka", Namespace = "http://tempuri.org/List.xsd")]
public List<Aka> Aka { get; set; }
}
[XmlRoot(ElementName = "sdnEntry", Namespace = "http://tempuri.org/List.xsd")]
public class SdnEntry
{
[XmlElement(ElementName = "lastName", Namespace = "http://tempuri.org/List.xsd")]
public string LastName { get; set; }
[XmlElement(ElementName = "fisrtName", Namespace = "http://tempuri.org/List.xsd")]
public string FisrtName { get; set; }
[XmlElement(ElementName = "akaList", Namespace = "http://tempuri.org/List.xsd")]
public AkaList AkaList { get; set; }
}
[XmlRoot(ElementName = "List", Namespace = "http://tempuri.org/List.xsd")]
public class List
{
[XmlElement(ElementName = "publshInformation", Namespace = "http://tempuri.org/List.xsd")]
public PublshInformation PublshInformation { get; set; }
[XmlElement(ElementName = "sdnEntry", Namespace = "http://tempuri.org/List.xsd")]
public SdnEntry SdnEntry { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
}
I personally would prefer the xml deserializer. It would be easy and more maintainable. Your underlying code, would remain the same and the deserialization can be done base on the Type T in your xml
I am trying to deserialize the below XML using C#
<?xml version="1.0" encoding="utf-8"?>
<Invoice>
<Samples>
<Sample>
<AccountId>1e547ae6-9a6d-d18f-958b-22000b83a845</AccountId>
<AccountNumber>55761598808</AccountNumber>
</Sample>
<Sample>
<AccountId>1e547ae6-9a6d-d18f-958b-22000b83a845</AccountId>
<AccountNumber>55761598808</AccountNumber>
</Sample>
</Samples>
</Invoice>
Here are the classes that I have defined to deserialize
[DataContract(Name = "Sample")]
public class Sample
{
[DataMember(Name = "AccountId")]
public string AccountId { get; set; }
[DataMember(Name = "AccountNumber")]
public string AccountNumber { get; set; }
}
[DataContract(Name = "Samples")]
public class Samples
{
[DataMember(Name = "Sample")]
public List<Sample> Sample { get; set; }
}
[DataContract(Name = "Invoice")]
public class Invoice
{
[DataMember(Name = "Samples")]
public Samples Samples { get; set; }
}
The corresponding test case to deserialize is as follows
public void SampleXmlTest()
{
dynamic env = SUT.GetEnvironment();
string dbConnStrUrjanet = (string)env.AvidUtility.UrjanetDB;
XmlSerializer deserializer = new XmlSerializer(typeof(CommonAvidXmlDto.Invoice));
TextReader reader = new StreamReader(#"C:\Users\SJuluru\Desktop\Sample XML\Samplexml.xml");
Object obj = deserializer.Deserialize(reader);
CommonAvidXmlDto.Invoice XmlData4 = (CommonAvidXmlDto.Invoice)obj;
After running the test case debug mode, XmlData4 has null without having the XML data. Kindly help me how to modify this code to work.
DataContract and DataMember are attribute of DataContractSerializer so you shoud replace your serializer msdn or use XmlSerializer's attributes (XmlRoot, XmlElement etc)
Change deserialize classes:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace ConsoleApp4
{
[XmlRoot(ElementName = "Sample")]
public class Sample
{
[XmlElement(ElementName = "AccountId")]
public string AccountId { get; set; }
[XmlElement(ElementName = "AccountNumber")]
public string AccountNumber { get; set; }
}
[XmlRoot(ElementName = "Samples")]
public class Samples
{
[XmlElement(ElementName = "Sample")]
public List<Sample> Sample { get; set; }
}
[XmlRoot(ElementName = "Invoice")]
public class Invoice
{
[XmlElement(ElementName = "Samples")]
public Samples Samples { get; set; }
}
}
Use below method for deserialize:
private static Invoice LoadInvoice(string fileName)
{
var serializer = new XmlSerializer(typeof(Invoice));
if (!File.Exists(fileName))
{
return null;
}
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return (Invoice)serializer.Deserialize(fs);
}
}
Result: