XML Serialize and Deserialize Issue for Complicated XML - c#

My XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ServerConfig loggingEnabled="1">
<Servers id="2" host="mytest">
<Server host="test1.example.com" port="9999" >
<Name id="newname1">
<FirstName id="myfirstname">hello first name</FirstName>
<SecondName id="myfirstname">hello first name</SecondName>
</Name>
</Server>
<Server host="test2.example.com" port="8888" />
</Servers>
<Servers id="1">
<Server host="test3.example.com" port="9899" >
<Name id="newname2">
<FirstName id="myfirstname">hello first name</FirstName>
</Name>
</Server>
<Server host="test4.example.com" port="8988" />
</Servers>
</ServerConfig>
I want to deserialize this xml to my class
Class
public sealed class ServerConfig
{
public sealed class Server
{
[XmlAttribute("host")]
public string Host { get; set; } // gives me host name
[XmlAttribute("port")]
public int Port { get; set; } // gives my prot number
}
[XmlArray]
public List<Server> Servers { get; set; } // gives me all 4 server lsit
[XmlAttribute("loggingEnabled")]
public int LoggingEnabled { get; set; } // gives me attribute detail
public ServerConfig()
{
Servers = null;
LoggingEnabled = 0;
}
}
Problem
My Problem is I don't know how to access the Attributes of the nested Element Name and sub nested element FirstName/SecondName
WIll be really very thankful.
Thanks.

The simplest way is being provided by Microsoft in VS 2012 onwards which is being brilliantly explained in this link.
XML TO C# Class
All you need to do is copy your xml and then paste special to a class as explained in the link.
Happy Coding.
Thanks,

Related

XML Config, How can I read a configuration file with a list/array of values rather than a single value

If I have a configuration file with the following list of values in the configuration.
The configuration file is an xml file...
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<Employees foor="bar">
<Employee name="aaa" surname="bbb"/>
<Employee name="ddd" surname="eee"/>
<Employee name="fff" surname="ggg"/>
</Employees>
</configuration>
Using Microsoft.Extensions.Configuration, I try to load the xml as follow
public class Employee
{
public string Name{get;set;}
public string Surname{get;set;}
}
...
public class Employees
{
public List<Employee> Employees{ get; set;}
public string Foo {get; set; }
}
...
var configurationBuilder = new ConfigurationBuilder()
AddXmlFile(path: "\\MyConfig.config")
.Build();
var employees = configurationBuilder.GetSection("Employees").Get<Employees>()
...
But the list returned is null, I am able to read single values if I move them up one level, but I would like to read a list of values inside my list.
It also does not work if I have a class within a class
For example
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<Outer foor="bar">
<Inner name="aaa" surname="bbb"/>
</Outer>
</configuration>
Scenario 1 - keeping the Employees xml wrapper element
In order to load the Employee xml elements, the corresponding property on the wrapper class must have the same name; so change Employees to Employee.
Lets also correct that foor attribute in the xml from <Employees foor="bar">
to <Employees foo="bar"> since the Employees class has a Foo property.
public class Employees
{
public List<Employee> Employee { get; set;}
public string Foo { get; set; }
}
Below shows the result of retrieving the employees section.
var employees = configurationBuilder.GetSection("Employees").Get<Employees>();
If you don't like the singular Employee property, then you can make that one private, but have to take that into account on retrieval.
You then define a public Employees as a 'pass through' property.
Note that you can't have an Employees class and a property with that same name because of an CS0542 compile error, which is to be fixed by renaming that class, to e.g. Staff.
public class Staff
{
private List<Employee> Employee { get; set; }
public List<Employee> Employees => Employee;
public string Foo { get; set; }
}
var employees = configurationBuilder.GetSection("Employees")
.Get<Staff>(o => o.BindNonPublicProperties = true);
Scenario 2 - not using an Employees xml wrapper element
Declare the xml as below.
<configuration>
<Employee name="aaa" surname="bbb" />
<Employee name="ddd" surname="eee" />
<Employee name="fff" surname="ggg" />
</configuration>
Retrieve the employees as a list of Employee.
var employees = configurationBuilder.GetSection("Employee").Get<List<Employee>>();
This is one of the way, you can do it as shown:
<util:list id="myColours" value-type="java.lang.String">
<value>red</value>
<value>green</value>
<value>blue</value>
<value>yellow</value>
<value>brown</value>
<value>orange</value>
</util:list>

How to deserialise a named XML node and grab all of its children C#

I've the following XML which I can deserialise in C#:
<?xml version="1.0" encoding="iso-8859-1" ?>
<ProductList>
<Product>
<MyDesc><![CDATA[DOCTOR WHO - PLANET OF THE DEA]]></MyDesc>
<ActualStock><![CDATA[5]]></ActualStock>
</Product>
</ProductList>
However, if I add a new node eg MetaData, I do not know how to grab that node and all of its children as text:
<?xml version="1.0" encoding="iso-8859-1" ?>
<ProductList>
<Product>
<MyDesc><![CDATA[DOCTOR WHO - PLANET OF THE DEA]]></MyDesc>
<ActualStock><![CDATA[5]]></ActualStock>
**<MetaData>
<Desc>MD-Description - This is my product desc</Desc>
<Image>MD - The main image</Image>
</MetaData>**
</Product>
</ProductList>
ie I want to grab and store everything within MetaData as one string. The trouble is the children of MetaData are unknown.
Is this possible?
I thought the deserialiser would use this to match the MetaData node:
[XmlElement("MetaData")]
public List<MetaData> MetaDataList
{
get
{
return metaDataList;
}
set
{
metaDataList = value;
}
}
and then figure out MetaData's children using:
private List<MetaData> metaDataList = new List<MetaData>();
public class MetaData
{
[XmlAnyElement]
public List<string> Children
{
get;
set;
}
}
As you can see I'm completely stuck...
Pointers would be appreciated.
Thanks.
Sai.

How can I store references to elements in my XML file? [duplicate]

This question already has answers here:
.net XML Serialization - Storing Reference instead of Object Copy
(2 answers)
Closed 8 years ago.
Let's say I have the following class layout which defines a one to many relationship between Company and Product:
public class Company
{
public string Name { get; set; }
public string Address { get; set; }
}
public class Product
{
public Company Manufacturer { get; set; }
public string Name { get; set; }
}
I would like to serialise this into XML, but unfortunately, the Company instance in Product will be duplicated. When I reserialise the document, the duplicated information will be reserialised into two distinct instances.
Because Company and Product are referenced later in the document, it is not possible to invert this relationship. What I need is some method of generating a document that looks like this:
<rootElement>
<companies>
<company>
<id>1</id>
<name>Apple</name>
<address>1 Infinite Loop... etc</address>
</company>
<company>
<id>2</id>
<name>Microsoft</name>
<address>1 Microsoft Way... etc</address>
</company>
</companies>
<products>
<product>
<companyId>1</companyId>
<name>iPhone</name>
</product>
<product>
<companyId>1</companyId>
<name>iMac</name>
</product>
<product>
<companyId>2</companyId>
<name>XBox 360</name>
</product>
</products>
</rootElement>
I'm confident that I can hack up some sort of specialised collection to rebuild these references myself, but I'd really like to know what the "correct" method of solving this issue is. There is no way that Microsoft have not thought of this, so there has to be something that I can use in .NET to solve this problem, but I just don't seem to be able to come up with the correct terms to search for.
If you are doing straight XML serialization and are only concerned about outbound serialization, then you can add an XMLIgnore attribute to the Manufacturer property in Product and add a companyId property for serialization:
[XMLIgnore()]
public Company Manufacturer { get; set; }
public int companyId {
get {
return this.Manufacturer.id;
}
set {
// Ignore any updates, only present to support XML serialization
}
}

List Collection XML Serialization

I've been playing around with the xml serialization for a while and I've hit a problem with serializing the a list collection. I want to serialize a list collection without the upper element wrapping around it. See example below:
Result serialization:
<?xml version="1.0" encoding="utf-8" ?>
<Person>
<Name>John</Name>
<AddressLine>
<string>Line 1</string>
<string>Line 2</string>
<string>Line 3</string>
</AddressLine>
<Telephone>123456789</Telephone>
</Person>
The serialization I want to output is:
<?xml version="1.0" encoding="utf-8" ?>
<Person>
<Name>John</Name>
<AddressLine>Line 1</AddressLine>
<AddressLine>Line 2</AddressLine>
<AddressLine>Line 3</AddressLine>
<Telephone>123456789</Telephone>
</Person>
I have tried setting different the attributes to my class I'm serializaing from but I can't seem to get anywhere with it. If anyone could show me what attributes I need to use to get my xml serialization to look like the ouput xml I want that would be greatly appreciated.
Cheers!
[Serializable]
public class Person
{
public string Name { get; set; }
[XmlElement]
public List<string> AddressLine { get; set; }
}
Produces desired output:
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>John</Name>
<AddressLine>1</AddressLine>
<AddressLine>2</AddressLine>
<AddressLine>3</AddressLine>
</Person>

XmlSerialization in C# - root element array

I would like to de/serialize a XML-Document with type=array as root node.
The given xml structure looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<parties type="array">
<party type="Person">
<id>1</id>
<lastname>Smith</lastname>
<firstname>Peter</firstname>
...
</party>
<party type="Person">
<id>2</id>
<lastname>Smith</lastname>
<firstname>Sarah</firstname>
...
</party>
<parties type="array">
C# Code looks like this:
[XmlRootAttribute("parties", Namespace = "", IsNullable = false)]
public class Parties
{
private ArrayList contacts = new ArrayList();
public Parties()
{
}
[XmlArray("parties"), XmlArrayItem("party", typeof(Person))]
public ArrayList Contacts
{
get { return contacts; }
set { contacts = value; }
}
}
The resulting xml output is this:
<?xml version="1.0" encoding="utf-8"?>
<parties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<parties>
<party>
<id>0</id>
<lastname>Smith</last-name>
<firstname>Peter</first-name>
</party>
</parties>
</parties>
The problem is that I have 2 -tags now.
How can I specify array type for the root element? Any ideas how to fix it without changing the given xml schema?
Try this:
[XmlElement("party")]
public ArrayList Contacts
{
get { return contacts; }
set { contacts = value; }
}

Categories