Deserialize a xml - c#

I need to create an object that can be deserialised from this XML
<Item>
<Description>Timber(dry)</Description>
<Measure Type="VOLUME">
<Value>1.779</Value>
<Units>m3</Units>
</Measure>
<Measure Type="WEIGHT">
<Value>925.08</Value>
<Units>Kilogram</Units>
</Measure>
<Measure>
<Value>1</Value>
<Units>Units</Units>
</Measure>
</Item>
My Problem is the Measure, it needs to be a list of some sort but when i create a
list it serialises incorrectly
<Item>
<Description>Timber(dry)</Description>
<Measures> <--- Dont want this <Measures> tag
<Measure Type="VOLUME">
<Value>1.779</Value>
<Units>m3</Units>
</Measure>
<Measure Type="WEIGHT">
<Value>925.08</Value>
<Units>Kilogram</Units>
</Measure>
<Measure>
<Value>1</Value>
<Units>Units</Units>
</Measure>
</Measures> <---
</Item>
This is what i have so far
public class Item
{
public Item()
{
this.Measures = new List<Measure>();
}
public string Description { get; set; }
public List<Measure> Measures { get; set; }
}
public class Measure
{
public string Value { get; set; }
public string Units { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Type { get; set; }
}

You need to decorate the Measures property with the [XmlElement] attribute, to indicate to the serializer that it needs to be serialized (and deserialized) as (bare) elements, instead of them being wrapped in another element.
public class StackOverflow_13188624
{
const string XML = #" <Item>
<Description>Timber(dry)</Description>
<Measure Type=""VOLUME"">
<Value>1.779</Value>
<Units>m3</Units>
</Measure>
<Measure Type=""WEIGHT"">
<Value>925.08</Value>
<Units>Kilogram</Units>
</Measure>
<Measure>
<Value>1</Value>
<Units>Units</Units>
</Measure>
</Item>";
public class Item
{
public Item()
{
this.Measures = new List<Measure>();
}
public string Description { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "Measure")]
public List<Measure> Measures { get; set; }
}
public class Measure
{
public string Value { get; set; }
public string Units { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Type { get; set; }
}
public static void Test()
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
XmlSerializer xs = new XmlSerializer(typeof(Item));
Item item = (Item)xs.Deserialize(ms);
Console.WriteLine(item.Measures);
}
}

Related

XML to object using YAXLib library

there is an xml of the form below, tell me how to deserialize it to get an object. using the YAXLib library
<catalog>
<categories>
<category id="1">category 1</category>
<category id="59349641">category 2</category>
<category id="303608809">category 3</category>
<category id="303614009">category 4</category>
<category id="303643009">category 5</category>
</categories>
</catalog>
how to get object from this xml ml with attributes
I tried this class but nothing is parsed
public class Сatalog
{
public List<Category> categories { get; set; }
}
public class Category
{
[YAXSerializeAs("id")]
public int Id { get; set; }
[YAXElementFor("category")]
public string category { get; set; }
[YAXSerializeAs("parentId")]
public int ParentId { get; set; }
}
tried like this
public class Сatalog
{
public List<string> categories { get; set; }
}
so we get only the text category
For anyone stumbling across a similar problem:
Here is the code to de/serialize:
[Test]
public void Xml_To_Object_YAXLib()
{
const string xml = #"<catalog>
<categories>
<category id=""1"">category 1</category>
<category id=""59349641"">category 2</category>
<category id=""303608809"">category 3</category>
<category id=""303614009"">category 4</category>
<category id=""303643009"">category 5</category>
</categories>
</catalog>";
var serializer = new YAXSerializer(typeof(Catalog),new SerializerOptions
{
ExceptionHandlingPolicies = YAXExceptionHandlingPolicies.ThrowWarningsAndErrors,
ExceptionBehavior = YAXExceptionTypes.Error,
SerializationOptions = YAXSerializationOptions.DontSerializeNullObjects
});
var deserialized = (Catalog) serializer.Deserialize(xml);
var serialized = serializer.Serialize(deserialized);
Assert.That(serialized, Is.EqualTo(xml));
Assert.That(deserialized.Categories.Count, Is.EqualTo(5));
Assert.That(deserialized.Categories[4].Id, Is.EqualTo(303643009));
}
And this is how to decorate classes with attributes to instruct the YAXSerializer:
[YAXSerializeAs("catalog")]
public class Catalog
{
[YAXSerializeAs("categories")]
public List<Category> Categories { get; set; }
}
and
[YAXSerializeAs("category")]
public class Category
{
[YAXSerializeAs("id")]
[YAXAttributeForClass]
public int Id { get; set; }
[YAXValueForClass]
public string CategoryName { get; set; }
/// <summary>
/// Assuming, this should also become an attribute to Category
/// (although DevOp's XML didn't contain it)
/// </summary>
[YAXSerializeAs("parentId")]
[YAXAttributeForClass]
[YAXErrorIfMissed(YAXExceptionTypes.Ignore)]
public int? ParentId { get; set; }
}

Unexpected results when serializing objects to XML

I am having issues creating the schema below...
<DocumentProperties>
<Document>
<Properties>
<propertyName>CNumber</propertyName>
<propertyValue>00645007803</propertyValue>
</Properties>
<targetFolder>\12345678\00645007803\</targetFolder>
</Document>
<Document>
<Properties>
<propertyName>CNumber</propertyName>
<propertyValue>00645007804</propertyValue>
</Properties>
<targetFolder>\12345678\00645007804\</targetFolder>
</Document>
</DocumentProperties>
I created the following classes to do this
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
public class Properties
{
public string propertyName { get; set; }
public string propertyValue { get; set; }
}
public class RetrieveMultipleDocumentsRequest
{
public SystemProperty SystemProperty { get; set; }
public RequestProperty RequestProperty { get; set; }
public DocumentProperties DocumentProperties { get; set; }
}
The output I am getting is "Document" and "Properties" twice as a parent child of each other. How do I resolve this?
Output from my classes
<DocumentProperties>
<Document>
<Document>
<Properties>
<Properties>
<propertyName>DizzzyGelespe</propertyName>
<propertyValue>8E077A60</propertyValue>
</Properties>
<Properties />
</Properties>
<targetFolder>C:\BXml\TargetFolder\</targetFolder>
</Document>
</Document>
</DocumentProperties>
Code that is generating the output:
public string Serialize(RetrieveMultipleDocumentsRequest details)
{
XmlSerializer serializer = new XmlSerializer(typeof(RetrieveMultipleDocumentsRequest));
using(StringWriter textWriter = new StringWriter())
{
serializer.Serialize(textWriter, details);
return textWriter.ToString();
}
}
You will need to annotate your object model as shown below in order to change the default serialization behavior. This application of the XmlElement attribute will prevent emiting out the parent tag based upon the encountered property and instead only emit out the containing data.
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
[XmlElement("Document")]
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
[XmlElement("Properties")]
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
Apparently your naming convention confused the XML serializer a bit. Just explicitly decorate the elements as below and it should work fine:
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
[XmlElement("Document")]
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
[XmlElement("Properties")]
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
Your problem here is with naming.
A list of documents should be called "documents" not "document", same goes for properties.
If you make these naming changes then you will see that your XML output is correct and makes sense.

Deserialization XmlArray not populating

I am trying to deserialize a XML response from an API using C#. I am not able to get the values of the ItemList element. I am able to get the other elements besides the ItemList. A sample XML is below and Classes below that, and finally the serialize function.
XML:
<Root xmlns="http://whatever">
<Child1>
<ChildElement1>16f09999</ChildElement1>
</Child1>
<ItemList>
<Element1>
...
</Element1>
<Item>
<ItemElem1>12345567</ItemElem1>
<ItemElem2>12356465784</ItemElem2>
...
<ItemAttributes>
...
</ItemAttributes>
</Item>
<Item>
...
</Item>
</ItemList>
</Root>
[Serializable()]
[System.Xml.Serialization.XmlRoot("Root")]
public class ResponseClass
{
[System.Xml.Serialization.XmlElement("Child1")]
public OperationRequest OperationRequest { get; set; }
[System.Xml.Serialization.XmlElement("ItemList")]
public ItemList ItemList { get; set; }
}
Class:
[Serializable()]
[System.Xml.Serialization.XmlRoot(ElementName = "ItemList")]
public class ItemList
{
[XmlArray("ItemList")]
[XmlArrayItem("Item", typeof(Item))]
public Item item { get; set; }
[System.Xml.Serialization.XmlElement("Element1")]
public int Element1 { get; set; }
}
Serializer:
XmlSerializer serializer = new XmlSerializer(typeof(ResponseClass));
StreamReader reader = new StreamReader(path);
response = (ResponseClass)serializer.Deserialize(reader);
reader.Close();
Please try the following. Since ItemList/Item is not a XmlArray, you need to define it as a simple XmlElement.
[Serializable()]
[System.Xml.Serialization.XmlRoot(ElementName = "Root", Namespace = "http://whatever")]
public class ResponseClass
{
[System.Xml.Serialization.XmlElement("Child1")]
public OperationRequest OperationRequest { get; set; }
[System.Xml.Serialization.XmlElement("ItemList")]
public ItemList ItemList { get; set; }
}
[Serializable()]
[System.Xml.Serialization.XmlRoot(ElementName = "ItemList", Namespace = "http://whatever")]
public class ItemList
{
[System.Xml.Serialization.XmlElement("Item")]
public Item[] Items { get; set; }
[System.Xml.Serialization.XmlElement("Element1")]
public int Element1 { get; set; }
}

Deserialize XML string not working

I have this XML string
<Root>
<Row>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</Row>
<Row>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</Row>
<Row>
<ITEMNO>2</ITEMNO>
<PARTSOURCE>MAKE</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>651321</CUSTPARTNO>
<DESCRIPT>Make Part</DESCRIPT>
</Row>
</Root>
I am trying to Deserialize it into this Root class
public class Root
{
public BOMItems Row { get; set; }
}
public class BOMItems
{
public string ITEMNO { get; set; }
public string USED { get; set; }
public string PARTSOURCE { get; set; }
public string QTY { get; set; }
public string CUSTPARTNO { get; set; }
public string CREV { get; set; }
public string DESCRIPT{ get; set; }
}
Using this method:
public Root TransformXMLToClass(string pXml)
{
var serializer = new XmlSerializer(typeof(Root));
XmlReader reader = XmlReader.Create(new StringReader(pXml));
return (Root)serializer.Deserialize(reader);
}
This works only on the first node.
I have tried changing the Root class like this:
public List<BOMItems> Row{get;set;}
It didn't work for any of the nodes
How do I get it to deserialize all nodes?
In your case it's quite simple. You just need to tell the serializer how to handle the collection of elements.
You do need to have the property as a collection or array like this:
public class Root
{
[XmlElement("Row")]
public BOMItems[] Row { get; set; }
}
The "[XmlElement]" is what will tell it how to deserialize correctly. Adding the XmlElementAttribute tells the serializer to treat it as a "flat" sequence.
<!-- Row Elements Flattened -->
<Root>
<Row>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</Row>
<Row>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</Row>
</Root>
<!-- Versus Row Elements Unflattened -->
<Root>
<Row>
<BOMItems>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</BOMItems>
<BOMItems>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</BOMItems>
</Row>
</Root>
Your BOM class should be something like below,
[XmlElement("ITEMNO")]
public string ITEMNO { get; set; }
so as to inform the serializer that you read ITEMNO and save it in the ITEMNO
EDIT:
It has to be done for every property of BOM class.
Answer: (with the list )
public class Root
{
[XmlElement("Row")]
public List<BOMItems> Row { get; set; }
}
public class BOMItems
{
[XmlElement("ITEMNO")]
public string ITEMNO { get; set; }
[XmlElement("USED")]
public string USED { get; set; }
[XmlElement("PARTSOURCE")]
public string PARTSOURCE { get; set; }
[XmlElement("QTY")]
public string QTY { get; set; }
[XmlElement("CUSTPARTNO")]
public string CUSTPARTNO { get; set; }
[XmlElement("CREV")]
public string CREV { get; set; }
[XmlElement("DESCRIPT")]
public string DESCRIPT { get; set; }
}
class Program
{
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(Root));
var reader = XmlReader.Create(new StringReader(File.ReadAllText("c:\\tet.xml")));
var serializedOutput = (Root)serializer.Deserialize(reader);
Console.ReadKey();
}

Deserialize XML with multiple namespaces to objects

I´m trying to deserialize this XML to objects in C# .NET 4.5:
<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"
xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
<item id="28" parentID="19" restricted="1">
<dc:creator>Alicia Keys</dc:creator>
<dc:date>2003-01-01</dc:date>
<dc:title>Gangsta Lovin&apos; (feat. Alicia Keys)</dc:title>
</item>
</DIDL-Lite>
Code:
I´m not getting any "item" Lists. The object isn't deserialized.
MemoryStream reader = new MemmoryStream(System.Text.Encoding.Unicode.GetBytes(Result));
var ser = new XmlSerializer(typeof(DIDLLite));
DIDLLite device = (DIDLLite)ser.Deserialize(reader);
Class DIDLLite:
[XmlRoot("DIDL-Lite", Namespace = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/")]
public class DIDLLite {
DIDLLite() {
this.serviceItem = new List<ContainerItem>();
}
[System.Xml.Serialization.XmlArrayItem("item", typeof(ServiceListTypeService), IsNullable = false)]
List<ContainerItem> serviceItem = new List<ContainerItem>();
}
Class ContainerItem:
public class ContainerItem
{
[System.Xml.Serialization.XmlAttribute("id")]
public string id { get; set; }
[System.Xml.Serialization.XmlAttribute("parentID")]
public string parentID { get; set; }
[System.Xml.Serialization.XmlAttribute("restricted")]
public string restricted { get; set; }
[System.Xml.Serialization.XmlAttribute("searchable")]
public string searchable { get; set; }
public string title { get; set; }
}
You have several issues:
you define an XmlArrayItem attribute - but really, in your XML, you don't have any list of items. If you want to use an Xml array construct, you'd need to have something like this for your XML:
<DIDL-Lite .....>
<Items>
<item id="28" parentID="19" restricted="1">
......
</item>
<item id="29" parentID="19" restricted="1">
......
</item>
</Items>
</DIDL-Lite>
So you would need to have an <Items>...</Items> wrapper around your <item> elements.
You have this declaration:
[XmlArrayItem("item", typeof(ServiceListTypeService), IsNullable = false)]
but where is the ServiceListtypeService defined? I don't see any trace of it....
I simplified your code a bit - and this works just fine:
[XmlRoot("DIDL-Lite", Namespace = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/")]
public class DIDLLite
{
[XmlElement("item")]
public ContainerItem Item { get; set; }
}
public class ContainerItem
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlAttribute("parentID")]
public string parentID { get; set; }
[XmlAttribute("restricted")]
public string restricted { get; set; }
[XmlAttribute("searchable")]
public string searchable { get; set; }
// you were missing these elements and their namespace
[XmlElement(Namespace = "http://purl.org/dc/elements/1.1/")]
public string creator { get; set; }
[XmlElement(Namespace = "http://purl.org/dc/elements/1.1/")]
public string date { get; set; }
[XmlElement(Namespace = "http://purl.org/dc/elements/1.1/")]
public string title { get; set; }
}
And now, when I run your code to deserialize your XML, I do get the objects filled nicely.

Categories