Recursive XML Deserialization - c#

I have some XML that I am trying to deserialize the xml below.
<?xml version="1.0" encoding="UTF-8"?>
<disproot version="1.0">
<header>
<msg-type> init_req </msg-type>
<txn-id> 0090 </txn-id>
</header>
<body />
</disproot>
My object is something like this.
[XmlRoot("disproot")]
public class Request
{
[XmlAttribute("version")]
public string Version
{ get; set; }
[XmlElement("header", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
Header header = new Header();
}
public class Header
{
public Header()
{
}
[XmlElement("txn-id")]
public string TransactionId
{
get;
set;
}
[XmlElement("msg-type")]
public string MessageType
{
get;
set;
}
}
My Header's object is not populated. The members are displaying as Null values. See below.
Request.Header.TasnsactionId's value is Null
Request.Header.MessageType's value is also Null
Anything wrong I am doing here?
Any help would be appreciable.

XML serialization works only on public members. So, you can change the field to
public Header header = new Header();
and it should work fine. Although I would advise you against using public fields, you should probably make it into a property:
public Header Header { get; set; }

Related

c# serialize object without root element

I am working with a 3rd party who has an xml structure for multiple different requests.
Each request has a common header structure and then some specific footer data.
Unfortunately, the header and footer sections are not wrapped within their own element tags and this is something that I can't change.
Some sample contrived requests are shown below:
Sample Request 1
<?xml version="1.0" encoding="UTF - 8" standalone="yes"?>
<Request>
<RequestType>1</RequestType>
<User>User01</User>
<id>1234</id>
<Name>John</Name>
<Age>20</Age>
</Request>
Sample Request 2
<?xml version="1.0" encoding="UTF - 8" standalone="yes"?>
<Request>
<RequestType>2</RequestType>
<User>User02</User>
<id>1235</id>
<School>The School</School>
<Teacher>Mrs Smith</Teacher>
</Request>
Sample Request 3
<?xml version="1.0" encoding="UTF - 8" standalone="yes"?>
<Request>
<RequestType>3</RequestType>
<User>User01</User>
<id>223</id>
<Work>The Office</Word>
<Boss>Mr White</Boss>
<Phone>1234567</Phone>
<Payday>Friday</Payday>
</Request>
You can see that each request has a RequestType, User and id.
My question relates to writing C# code that will encapsulate this Xml for serialization.
To me, it seems wrong to have each of my C# classes having the repeated header (RequestType, User and id) data.
I have tried using generics (see sample code below) but that leads to my question.
Question: How can I serialize my generic object Footer so that it is not wrapped within "root" Footer element?
[System.Xml.Serialization.XmlRoot("Request")]
public class GenericRequest<typeT>
{
public GenericRequest()
{
}
public int RequestType { get; set; }
public string User { get; set; }
public int id { get; set; }
public typeT Footer { get; set; }
}
You can create a class with interface IFooter, which can have different implementor as per requirement (e.g.
interface IFooter : ISerializable
{
//Define common member.
}
public class Footer1: IFooter
{
// define members (e.g. work)
}
public class Footer2: IFooter
{
// define members
}
public class Footer3: IFooter
{
// define members
}
Now serialize main class
[System.Xml.Serialization.XmlRoot("Request")]
public class GenericRequest
{
public GenericRequest()
{
}
public int RequestType { get; set; }
public string User { get; set; }
public int id { get; set; }
public IFooter Footer { get; set; }
}
Visit How can I serialize an object that has an interface as a property? for reference.

C# Deserialization xml file

I try to deserialize xml file:
<?xml version="1.0" encoding="utf-8"?>
<XmlFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OBJECTS ITEM="ItemValue" TABLE_NAME="TableExample">
</OBJECTS>
</XmlFile>
My deserialize class code looks like that:
[Serializable]
[XmlRoot("XmlFile")]
public class SerializeObject
{
[XmlAttribute("ITEM")]
public string Item { get; set; }
[XmlAttribute("TABLE_NAME")]
public string Table_Name { get; set; }
}
When I try deserialize xml file i always got no errors and Item and Table_Name equals null. Why?
Thx for replay
[XmlRoot("XmlFile")]
public class SerializableContainer
{
[XmlElement("OBJECTS")]
public SerializeObject[] Objects { get; set; }
}
public class SerializeObject
{
[XmlAttribute("ITEM")]
public string Item { get; set; }
[XmlAttribute("TABLE_NAME")]
public string Table_Name { get; set; }
}
And then you deserialize with:
var serializer = new XmlSerializer(typeof(SerializableContainer));
using (var file = File.OpenText("sample.xml"))
{
var data = (SerializableContainer)serializer.Deserialize(file);
// ...
}
leaving here a more complete example in case anyone needs: http://davidsonsousa.net/en/post/serializedeserialize-objects-to-xml-with-c
Cheers!

Get null by deserialize in C# from XML if string between tags

i need some help, i get allways null if i will deserialize a string between two xml tags.
The following example xml file:
<?xml version="1.0" encoding="utf-8" ?>
<item name='First Item' size='1'>
<Bits value='0'>
1st String
</Bits>
<Bits value='1'>
2nd String
</Bits>
</item>
And i write the following classes:
[Serializable()]
public class Bits
{
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
[XmlAttribute("value")]
public int entryValue { get; set; }
}
[Serializable()]
[XmlRoot("item")]
public class itemsReader
{
public itemsReader()
{
_bitList = new List<Bits>();
}
[XmlElement("Bits")]
public List<Bits> _bitList { get; set; }
[XmlAttribute("name")]
public String entryName { get; set; }
[XmlAttribute("size")]
public int entrySize { get; set; }
}
Only the entryString is always null!
To readout the XML file i use the following:
itemsReader ireader = null;
String path = #"PathtoString";
XmlSerializer serializer = new XmlSerializer(typeof(itemsReader));
var reader = File.OpenText(path);
ireader = (itemsReader)serializer.Deserialize(reader);
Thanks for help!
You have decorated entryString with XmlElement attribute which will search for an element Bits inside Bits itself.
But you want inner text of Bits element. For that we have another attribute called XmlText.
So change this
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
to
[XmlText]
public String entryString { get; set; }
i ran your code on your input and got the output, but the i saw, in the Bits class, that the property entryString has an attribute
[XmlElement(ElementName = "Bits")]
but in your xml file there is no <Bits> tags around 1st String. so i added them and got:
<?xml version="1.0"?>
<item name="First Item" size="2">
<Bits value="1">
<Bits>firstOne</Bits>
</Bits>
<Bits value="2">
<Bits>secOne</Bits>
</Bits>
</item>
and then your code worked
so you can change the xml file or get rid of the attribute. your call

Class not serializing as expected

I've been struggling with this all day. I done a lot of research, but I just can't seem to put it all together.
I have a XML response from a server like so:
<?xml version="1.0" ?>
<inboxRecords>
<inboxRecord>
<field1 />
<field2 />
<field3 />
</inboxRecord>
<inboxRecord>
<field1 />
<field2 />
<field3 />
</inboxRecord>
</inboxRecords>
I created the following code to represent the response. The intention is that I will de-serialize the response using the following:
[XmlRoot("inboxRecords")]
public sealed class QueueQueryResult
{
public InboxRecord[] InboxRecords;
public QueueQueryResult()
{
InboxRecords = null;
}
public sealed class InboxRecord
{
public string field1 { get; set; }
public string field2 { get; set; }
public string field3 { get; set; }
}
}
The classes above are based on one of the numerous examples I found online. The problem is, when I serialize the class above (to confirm that it is correct), it comes out like this:
<?xml version="1.0" encoding="utf-16"?>
<inboxRecords>
<InboxRecords>
<InboxRecord>
<field1>some value</field1>
</InboxRecord>
<InboxRecord>
<field1>some value</field1>
</InboxRecord>
</InboxRecords>
</inboxRecords>
So, first problem, how do I get rid of the extra InboxRecords element? I only want the root to say that (with a small 'i'). Second, for quick testing, I only put a value in the first field. Why didn't the other fields come out as empty elements? Do I need another decorator for that?
Thanks!
Thanks!
Use the XmlElement attribute:
[XmlRoot("inboxRecords")]
public sealed class QueueQueryResult
{
[XmlElement("inboxRecord")]
public InboxRecord[] InboxRecords;
public QueueQueryResult()
{
InboxRecords = null;
}
public sealed class InboxRecord
{
public string field1 { get; set; }
public string field2 { get; set; }
public string field3 { get; set; }
}
}
This removes the Array wrapper element and allows you to control the name for each xml element so that you can use lower case names.
Untested, but I reckon you could probably do something like this:
[XmlRoot("inboxRecords")]
public sealed class QueueQueryResult : Collection<QueueQueryResult.InboxRecord>
{
public QueueQueryResult()
{
InboxRecords = null;
}
public sealed class InboxRecord
{
public string field1 { get; set; }
public string field2 { get; set; }
public string field3 { get; set; }
}
}
The problem with your code is that you've got a member InboxRecords within an object that is serialising to inboxRecords. By making the class inherit from Collection, you're providing it with the capability to handle a set of InboxRecords without the extra inner element.
After generating an XSD from your first sample XML (and then a .cs) using xsd.exe, I can create and serialize an instance from your second example:
<?xml version="1.0" encoding="utf-16"?>
<inboxRecords xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<inboxRecord>
<field1>some value</field1>
</inboxRecord>
<inboxRecord>
<field1>some value</field1>
</inboxRecord>
</inboxRecords>
With the exception of the encoding attribute and the schema namespace, this looks pretty darn similar to the first sample.

Controlling XML Serialization of a List<> derived class

I'm converting a Dictionary object into a List<> derived class by means of the following two declarations:
[Serializable]
public class LogItem
{
public string Name { get; set; }
public string Value { get; set; }
public LogItem(string key, string value)
{
Name = key; Value = value;
}
public LogItem() { }
}
public class SerializableDictionary : List<LogItem>
{
public SerializableDictionary(Dictionary<string, string> table)
{
IDictionaryEnumerator index = table.GetEnumerator();
while (index.MoveNext())
{
Put(index.Key.ToString(), index.Value.ToString());
}
}
private void Put(string key, string value)
{
base.Add(new LogItem(key, value));
}
}
I intend to serialize SerializableDictionary by means of the following code:
SerializableDictionary log = new SerializableDictionary(contents);
using (StringWriter xmlText = new StringWriter())
{
XmlSerializer xmlFormat =
new XmlSerializer(typeof(SerializableDictionary), new XmlRootAttribute("Log"));
xmlFormat.Serialize(xmlText, log);
}
Works fine, but I'm unable to change the XML formatting.
This XML document is intended to be sent to a xml database field and is not meant to be deserialized.
I'd rather have both Name and Value
formatted as attributes of the
LogItem element.
However any attempts at using XMLAttribute have resulted in Reflection or compilation errors. I'm at loss as to what I can do to achieve this requirement. Could someone please help?
you can annotate them with XmlAttribute:
[Serializable]
public class LogItem
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Value { get; set; }
public LogItem(string key, string value)
{
Name = key; Value = value;
}
public LogItem() { }
}
This worked fine for me and produced the following XML (based on sample input):
<?xml version="1.0" encoding="utf-16"?>
<Log xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LogItem Name="foo" Value="bar" />
<LogItem Name="asdf" Value="bcxcvxc" />
</Log>
There must be something else going on besides what you are showing. I am able to compile and execute the above code both with and without the XmlAttribute attribute applied to the Name and Value properties.
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Value { get; set; }

Categories