Ds-serializing Xml to POCO objects array/list in C# - c#

I have a xml files in following format:
<?xml version=""1.0"" encoding=""UTF-8""?>
<Options>
<Header>
<H1>A</H1>
<H2>B</H2>
<H3>C</H3>
</Header>
<Include>
<Option A1="something" A2="something">SomeValue</Option>
<Option A1="something" A2="something">SomeOtherValue</Option>
</Include>
</Options>
I managed to use a serializer to de-serialize headers, but run into trouble with options. Specifically I have the following C# objects:
[XmlRoot(ElementName="Option")]
public class Option {
[XmlAttribute(AttributeName="A1")]
public string A1 { get; set; }
[XmlAttribute(AttributeName="A2")]
public string A2 { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="Include")]
public class OptionList {
[XmlArrayItem("Option")]
public List<Option> Options { get; set; }
}
And I use this serializer to do conversion:
public IReadOnlyList<Option> ParseInclude(string xmlDocument)
{
using (var reader = new XmlTextReader(new StringReader(xmlDocument)))
{
var serializer = new XmlSerializer(typeof(OptionList));
reader.ReadToFollowing("Include");
var collection = (OptionList) serializer.Deserialize(reader);
return collection .Options ;
}
}
But I cannot get it work - I am constantly getting NullReferenceException at the return statement because Options is null. Any ideas?

Try following :
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)
{
string xmlDocument = File.ReadAllText(FILENAME);
using (XmlReader reader = XmlReader.Create(new StringReader(xmlDocument)))
{
XmlSerializer serializer = new XmlSerializer(typeof(Option));
Option collection = (Option)serializer.Deserialize(reader);
}
}
}
[XmlRoot(ElementName = "Options")]
public class Option
{
public Header Header { get; set; }
[XmlArray("Include")]
[XmlArrayItem("Option")]
public List<OptionList> Options { get; set; }
}
public class Header
{
public string H1 { get; set; }
public string H2 { get; set; }
public string H3 { get; set; }
}
public class OptionList
{
[XmlAttribute(AttributeName = "A1")]
public string A1 { get; set; }
[XmlAttribute(AttributeName = "A2")]
public string A2 { get; set; }
[XmlText]
public string Text { get; set; }
}
}

Related

XmlSerializer returns null

I have an XML that i am trying to serialize to a class but i am unable to fathom why the object is null.
null object
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns0:vendResponse xmlns:ns0="http://mynamespace.co/ns0">
<ns0:sequence>234532532221</ns0:sequence>
<ns0:CId>0</ns0:CId>
<ns0:RefId>202675454545453434343</ns0:RefId>
<ns0:origAcct>20.00</ns0:origAcct>
<ns0:destAcct>00087646564</ns0:destAcct>
<ns0:responseCode>0</ns0:responseCode>
<ns0:responseMessage>Successful</ns0:responseMessage>
</ns0:vendResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
var contentStream = File.ReadAllText("response.xml");
Envelope resultEnvelope = new Envelope();
using (var stringReader = new StringReader(contentStream))
{
using (XmlReader reader = new XmlTextReader(stringReader))
{
var serializer1 = new XmlSerializer(typeof(Envelope));
resultEnvelope = serializer1.Deserialize(reader) as Envelope;
}
}
the soap Envelope class generated in VS using paste XML as classes:
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.Data;
namespace ConsoleApplication23
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement("Body")]
public Body body { get; set; }
}
public class Body
{
[XmlElement(ElementName = "vendResponse", Namespace = "http://mynamespace.co/ns0")]
public VendResponse vendResponse { get; set; }
}
public class VendResponse
{
public string sequence { get; set; }
public string CId { get; set; }
public string RefId { get; set; }
public string origAcct { get; set; }
public string destAcct { get; set; }
public int responseCode { get; set; }
public string responseMessage { get; set; }
}
}

Deserialize XML same items with different tag

This is an XML example I want to deserialize and use in a Desktop App, where the user could insert an XML like this one:
<Settings>
<FileName>C:\Users\myniceuser\Desktop\hello.xmldoc</FileName>
<Zones>
<Row1>
<Address>2</Address>strong text
<Zone>2</Zone>
<Installed>True</Installed>
</Row1>
<Row2>
<Address>3</Address>
<Zone>2</Zone>
<Installed>True</Installed>
</Row2>
<Row3>
<Address>4</Address>
<Zone>2</Zone>
<Installed>True</Installed>
</Row3>
<Row4>
<Address>5</Address>
<Zone>2</Zone>
<Installed>True</Installed>
</Row4>
</Zones>
<Network_IP>010.000.008.072</Network_IP>
<Ethernet_Enable>true</Ethernet_Enable>
<Language>1</Language>
</Settings>
The class I implemented is this one:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace MyApp.Models
{
[XmlRoot(ElementName = "Settings")]
public class XML_Settings
{
[XmlElement(ElementName = "FileName")]
public string FileName { get; set; }
//[XmlElement(ElementName = "Zones")]
[XmlElement(ElementName ="Zones")]
public Zones_Points[] Zones_Points { get; set; }
[XmlElement(ElementName = "Network_IP")]
public string NetworkIP { get; set; }
[XmlElement(ElementName = "Ethernet_Enable")]
public bool EthernetEnable { get; set; }
[XmlElement(ElementName = "Language")]
public int Language { get; set; }
}
[XmlRoot(ElementName = "")]
public partial class Zones_Points
{
[XmlElement(ElementName ="Address")]
public int Address { get; set; }
[XmlElement(ElementName ="Zone")]
public int PointZone { get; set; }
[XmlElement(ElementName ="Installed")]
public bool Installed { get; set; }
}
}
I deserialize like this:
Models.XML_Settings inputted_xml = new();
using StreamReader stream_xml = new StreamReader(xmlfile_path, CodePagesEncodingProvider.Instance.GetEncoding(1253));
XmlSerializer serializer = new XmlSerializer(typeof(Models.XML_Settings));
try
{
Models.XML_Settings input = (Models.XML_GR6500)serializer.Deserialize(stream_xml);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
I want my app to input files in XML like this one, and convert their data to a class that i can use.
The object "input" created by the Deserialization got every data correct, except the Zones, those that in XML have the "Row" tags. Those "rows" could every time be more or less that 4.
What can I do to have the items with the row tags deserialized and inputted into a Zones_Points list or array?
Use IXmlSerializable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(XML_Settings));
XML_Settings settings = (XML_Settings)serializer.Deserialize(reader);
}
}
[XmlRoot("Settings")]
public class XML_Settings
{
[XmlElement(ElementName = "FileName")]
public string FileName { get; set; }
[XmlElement(ElementName = "Zones")]
public Zones_Points Zones_Point { get; set; }
[XmlElement(ElementName = "Network_IP")]
public string NetworkIP { get; set; }
[XmlElement(ElementName = "Ethernet_Enable")]
public bool EthernetEnable { get; set; }
[XmlElement(ElementName = "Language")]
public int Language { get; set; }
}
public partial class Zones_Points : IXmlSerializable
{
// Xml Serialization Infrastructure
[XmlElement(ElementName = "Zones")]
public List<Zones_Point> Points { get; set; }
public void WriteXml(XmlWriter writer)
{
}
public void ReadXml(XmlReader reader)
{
XElement zones = (XElement)XElement.ReadFrom(reader);
Points = new List<Zones_Point>();
foreach (XElement row in zones.Elements())
{
Zones_Point Point = new Zones_Point();
Points.Add(Point);
Point.Address = (int)row.Element("Address");
Point.PointZone = (int)row.Element("Zone");
Point.Installed = (Boolean)row.Element("Installed");
}
}
public XmlSchema GetSchema()
{
return (null);
}
}
public partial class Zones_Point
{
[XmlElement(ElementName = "Address")]
public int Address { get; set; }
[XmlElement(ElementName = "Zone")]
public int PointZone { get; set; }
[XmlElement(ElementName = "Installed")]
public bool Installed { get; set; }
}
}

How to Deserialize XML document?

How to Deserialize XML document
My XML
<Title>
<NAME>ABC</NAME>
<BODY>
<A>IAG4</A>
<B>
<B1>
<C>100</C>
<C>EC0001</C1>
<C2>DEF</C2>
<C3>100</C3>
<C4>200</C4>
<C5>600</C5>
<C6>1000</C6>
</B1>
<B1>
<D>101</D>
<D1>EC0002</D1>
</B1>
</B>
</BODY>
</Title>
I want to deserialize this into a class and I want to access them with the objects of the class created. I am using C#.
Use xml serialization code as shown 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(Message));
Message message = (Message)serializer.Deserialize(reader);
}
}
[XmlRoot("MESSAGE")]
public class Message
{
[XmlElement("NAME")]
public string name { get; set; }
[XmlElement("BODY")]
public Body body { get; set; }
}
public class Body
{
[XmlElement("EQPID")]
public string eqpid { get; set; }
[XmlArray("ECS")]
[XmlArrayItem("EC")]
public List<EC> ec { get; set; }
}
public class EC
{
public int ECID { get; set; }
public string ECNAME { get; set; }
public string ECDEF { get; set; }
public int ECSLL { get; set; }
public int ECSUL { get; set; }
public int ECWLL { get; set; }
public int ECWUL { get; set; }
}
}
You could use online tools like Xml2Csharp to generate classes needed to store your XML Data. To deserialize the Xml, you could then use the XmlSerializer
XmlSerializer serializer = new XmlSerializer(typeof(MESSAGE));
using (TextReader reader = new StringReader(xml))
{
var result = (MESSAGE)serializer.Deserialize(reader);
}
Where your classes are defined as
[XmlRoot(ElementName="EC")]
public class EC
{
[XmlElement(ElementName="ECID")]
public string ECID { get; set; }
[XmlElement(ElementName="ECNAME")]
public string ECNAME { get; set; }
[XmlElement(ElementName="ECDEF")]
public string ECDEF { get; set; }
[XmlElement(ElementName="ECSLL")]
public string ECSLL { get; set; }
[XmlElement(ElementName="ECSUL")]
public string ECSUL { get; set; }
[XmlElement(ElementName="ECWLL")]
public string ECWLL { get; set; }
[XmlElement(ElementName="ECWUL")]
public string ECWUL { get; set; }
}
[XmlRoot(ElementName="ECS")]
public class ECS
{
[XmlElement(ElementName="EC")]
public List<EC> EC { get; set; }
}
[XmlRoot(ElementName="BODY")]
public class BODY
{
[XmlElement(ElementName="EQPID")]
public string EQPID { get; set; }
[XmlElement(ElementName="ECS")]
public ECS ECS { get; set; }
}
[XmlRoot(ElementName="MESSAGE")]
public class MESSAGE
{
[XmlElement(ElementName="NAME")]
public string NAME { get; set; }
[XmlElement(ElementName="BODY")]
public BODY BODY { get; set; }
}

How do I Deserialize this XML document in C#

This is my XML:
<?xml version="1.0" encoding="utf-8"?>
<Fruit>
<Fruit_group name='Tropical'>
<fruit_types name ='Tropical Used'>
<fruit>bananas</fruit>
<fruit>mangoes</fruit>
</fruit_types>
</Fruit_group>
<Fruit_group name='Citrus'>
<fruit_types name ='Citruses Used'>
<fruit>orange</fruit>
<fruit>lime</fruit>
<fruit>grapefruit</fruit>
<excluded_fruits>
<fruit>mandarin</fruit>
</excluded_fruits>
</fruit_types>
</Fruit_group>
</Fruit>
And this is a sample of my XML text..
Is there a way to deserialize it and keep the name of the elements too..
I mean I would like to have like:
Tropical -> Tropical Used -> fruit -> bananas, mangoes
Citrus->Citruses Used ->
fruit = orange, lime, grapefruit
excluded = mandarin....
Something like this...
Could someone help me to understand how does this work?
You can use XML to c# website to create a class according to XML.
In this case, I've got this example
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName="fruit_types")]
public class Fruit_types {
[XmlElement(ElementName="fruit")]
public List<string> Fruit { get; set; }
[XmlAttribute(AttributeName="name")]
public string Name { get; set; }
[XmlElement(ElementName="excluded_fruits")]
public Excluded_fruits Excluded_fruits { get; set; }
}
[XmlRoot(ElementName="Fruit_group")]
public class Fruit_group {
[XmlElement(ElementName="fruit_types")]
public Fruit_types Fruit_types { get; set; }
[XmlAttribute(AttributeName="name")]
public string Name { get; set; }
}
[XmlRoot(ElementName="excluded_fruits")]
public class Excluded_fruits {
[XmlElement(ElementName="fruit")]
public string Fruit { get; set; }
}
[XmlRoot(ElementName="Fruit")]
public class Fruit {
[XmlElement(ElementName="Fruit_group")]
public List<Fruit_group> Fruit_group { get; set; }
}
}
Also, You could read this article about XML deserialization.
I suggest using xmltocsharp to convert the XML to Model and do required alterations. For example change the string to List<string> under Excluded_fruits
[XmlRoot(ElementName = "fruit_types")]
public class Fruit_types
{
[XmlElement(ElementName = "fruit")]
public List<string> Fruit { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "excluded_fruits")]
public Excluded_fruits Excluded_fruits { get; set; }
}
[XmlRoot(ElementName = "Fruit_group")]
public class Fruit_group
{
[XmlElement(ElementName = "fruit_types")]
public Fruit_types Fruit_types { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
}
[XmlRoot(ElementName = "excluded_fruits")]
public class Excluded_fruits
{
[XmlElement(ElementName = "fruit")]
public List<string> Fruit { get; set; }
}
[XmlRoot(ElementName = "Fruit")]
public class Fruit
{
[XmlElement(ElementName = "Fruit_group")]
public List<Fruit_group> Fruit_group { get; set; }
}
Once the model is ready, you can use XmlSerializer to Deserialize the xml file
using (StreamReader r = new StreamReader(xmlfilepath))
{
string xmlString = r.ReadToEnd();
XmlSerializer ser = new XmlSerializer(typeof(Fruit));
using (TextReader reader = new StringReader(xmlString))
{
var fruits = (Fruit)ser.Deserialize(reader);
foreach(var fruitgroup in fruits.Fruit_group)
{
Console.Write($"{fruitgroup.Name} -> ");
Console.Write($"{fruitgroup.Fruit_types.Name} -> ");
Console.Write($"fruit = {string.Join(",", fruitgroup.Fruit_types.Fruit.ToArray())}; ");
if (fruitgroup.Fruit_types.Excluded_fruits?.Fruit?.Count() > 0)
Console.Write($"excluded = {string.Join(",", fruitgroup.Fruit_types.Excluded_fruits.Fruit.ToArray())}{Environment.NewLine}");
else
Console.WriteLine();
}
}
}
I like getting flatter results doing a custom parsing using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Fruit_Group> groups = doc.Descendants("Fruit_group").Select(x => new Fruit_Group()
{
groupName = (string)x.Attribute("name"),
typeName = (string)x.Element("fruit_types").Attribute("name"),
fruits = x.Elements("fruit_types").Elements("fruit").Select(y => (string)y).ToArray(),
excluded = x.Descendants("excluded_fruits").Elements("fruit").Select(y => (string)y).ToArray()
}).ToList();
}
}
public class Fruit_Group
{
public string groupName { get; set;}
public string typeName { get; set; }
public string[] fruits { get; set; }
public string[] excluded { get; set; }
}
}

XML Parsing Steam Group API

I have a question:
How to parse XML in this specific document:
http://steamcommunity.com/groups/BotBrothers/memberslistxml/?xml=1&p=1
I want to get all the <STEAMID64>'s in a file document line by line
It's not duplicate of that other one, I need this one cuz it works diffrent.
Try code below. I had to change 1st line from standalone="true" to standalone="yes"
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)
{
string file = File.ReadAllText(FILENAME);
file = file.Replace("standalone=\"true\"", "standalone=\"yes\"");
StringReader reader = new StringReader(file);
XmlSerializer xs = new XmlSerializer(typeof(MemberList));
MemberList members = (MemberList)xs.Deserialize(reader);
}
}
[XmlRoot("memberList")]
public class MemberList
{
[XmlElement("groupID64")]
public string groupID64 { get; set;}
[XmlElement("groupDetails")]
public GroupDetails groupDetails { get; set;}
[XmlElement("nextPageLink")]
public Text nextPageLink { get; set; }
[XmlElement("members")]
public Members members { get; set; }
}
[XmlRoot("groupDetails")]
public class GroupDetails
{
[XmlElement("groupName")]
public Text groupName { get; set; }
[XmlElement("groupURL")]
public Text groupURL { get; set; }
[XmlElement("headline")]
public Text headline { get; set; }
[XmlElement("summary")]
public Text summary { get; set; }
[XmlElement("avatarIcon")]
public Text avatarIcon { get; set; }
[XmlElement("avatarMedium")]
public Text avatarMedium { get; set; }
[XmlElement("avatarFull")]
public Text avatarFull { get; set; }
[XmlElement("memberCount")]
public int memberCount { get; set; }
[XmlElement("membersInChat")]
public int membersInChat { get; set; }
[XmlElement("membersInGame")]
public int membersInGame { get; set; }
[XmlElement("membersOnline")]
public int membersOnline { get; set; }
}
public class Text
{
[XmlText]
public string text { get; set;}
}
[XmlRoot("members")]
public class Members
{
[XmlElement("steamID64")]
public List<string> steamID64 { get; set;}
}
}
​
Simple solution to get the steamID64 and fix the error in the XML
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string file = File.ReadAllText(FILENAME);
file = file.Replace("standalone=\"true\"", "standalone=\"yes\"");
XDocument doc = XDocument.Parse(file);
List<string> steamID64 = doc.Descendants("steamID64").Select(x => (string)x).ToList();
}
}
}​

Categories