Deserialize XML list of elements of string element each - c#

I'm not able to deserialize the following secition of an XML with C#
<mainfile>
<portfolio>
<fotos>
<foto> <!CDATA[https://whatever.com/fotos/E/400/photo.JPG]]>
</foto>
</fotos>
</portfolio>
<portfolio>
<fotos>
<foto> <!CDATA[https://whatever.com/fotos/E/400/photo1.JPG]]>
</foto>
</fotos>
</portfolio>
</mainfile>
I think it should be quite straight forward, but when deserializing it always returns an empty list. Here is the code:
[XmlRoot("mainfile")]
public class MainFile
{
public MainFile()
{
porftolios= new List<Portfolio>();
}
[XmlElement("portfolio")]
public List<Portfolio> Portfolios{ get; set; }
}
public class Portfolio
{
....
[XmlElement("fotos")]
public List<Foto> Fotos { get; set; }
}
public class Foto
{
[XmlText]
public string data{ get; set; }
}
Thanks.
EDIT.
From HimBromBeere's solution i've chaged the following code, with a successful result:
public class Portfolio
{
....
[XmlArray("fotos")]
[XmlArrayItem("foto")]
public List<Foto> Fotos { get; set; }
}
public class Foto
{
[XmlText]
public string data{ get; set; }
}

When using XmlElement for list-types the container-list-element within the resulting xml is lost. As you do have that container for your fotos-tag, you should use XmlArrayItem for it:
public class Portfolio
{
[XmlArray("fotos")]
[XmlArrayItem("foto")]
public List<Foto> Fotos { get; set; }
}
If you can change the xml however I would suggest to use a consistent style for your collections, either use the container for your portfolio also, or omit it for your fotos.

Related

Deserializing XML to class, some elements not not pulling through

I am having some difficulties figuring out how to correctly structure my classes to mirror the XML that I am attempting to deserialize. Most elements are coming through, but for example, in the XML below the UOMs object is not being deserialized.
Example XML:
<Items xmlns="http://www.manh.com/ILSNET/Interface" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Item>
<Desc>Desc Field Example Value</Desc>
<Item>PE0000009790</Item>
<ItemCategories>
<Action>SAVE</Action>
<Category1>COMPONENT</Category1>
<Category2>Category2ExampleValue</Category2>
</ItemCategories>
<ItemClass>
<Action>SAVE</Action>
<ItemClass>Example ItemClass</ItemClass>
</ItemClass>
<UOMS>
<UOM>
<Action>SAVE</Action>
<ConvQty>1</ConvQty>
<DimensionUm>IN</DimensionUm>
<Height>0.0</Height>
<Length>0.0</Length>
<QtyUm>EA</QtyUm>
<Sequence>1</Sequence>
<Weight>0</Weight>
<WeightUm>LB</WeightUm>
<Width>0.0</Width>
</UOM>
</UOMS>
</Item>
</Items>
I am using basic XML deserialization code, which works well but just providing for background:
using (FileStream fileStream = new FileStream(Filename, FileMode.Open))
{
this.CreatedObjects = (ItemList)serializer.Deserialize(fileStream);
}
The first class is below:
[XmlRoot(ElementName = "Items", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemList
{
[XmlElement("Item")]
public Item[] Items { get; set; }
}
public class Item
{
[XmlElement("ItemCategories")]
public ItemCategory[] Categories { get; set; }
[XmlElement("ItemClass")]
public ItemClass[] Classes { get; set; }
[XmlElement("UOMS")]
public ItemUOMS UOMs { get; set; }
[XmlElement("Desc")]
public string Description { get; set; }
[XmlElement("Item")]
public string Id { get; set; }
}
The second class, which I am struggling to populate, is below (this class is a member of the Item class shown above:
[XmlRoot(ElementName = "UOMS", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemUOMS
{
[XmlElement("UOM")]
public ItemUOM[] UOM { get; set; }
}
[XmlRoot(ElementName = "UOM", Namespace = "http://www.manh.com/ILSNET/Interface")]
public class ItemUOM
{
[XmlElement("Action")]
public string Action { get; }
[XmlElement("DimensionUm")]
public string DimensionUnit { get; }
[XmlElement]
public decimal Height { get; }
[XmlElement]
public decimal Length { get; }
[XmlElement("QtyUm")]
public string QtyUnit { get; }
[XmlElement("ConvQty")]
public decimal Quantity { get; }
[XmlElement]
public int Sequence { get; }
[XmlElement]
public decimal Weight { get; }
[XmlElement("WeightUm")]
public string WeightUnit { get; }
[XmlElement]
public decimal Width { get; }
}
Unfortunately, I don't get an error, but instead the UOMs objects are just default objects without any values being set. I tried to reference some XML to C# Class tools online that are supposed to output C# classes for you based on XML provided to the tool, but their classes didn't seem to solve the issue for me either. I attempted to use [XmlArray] / [XmlArrayItem], but neither had any effect either.
If you need any more information from me, please let me know. Thanks for any assistance/guidance you are able to provide in advance.

Deserialize XML element returning null value

I have some data in an XML file. I am trying to deserialize the XML to some classes I have created.
I have been able to deserialize all the attributes of the PointCode and CodeAttributes elements. However, I can't seem to get the TextListValue attribute of the textList element.
The textList element returns a null value.
I am using c# and using System.Xml.Serialization
[XmlRoot("PointCode")]
public class PointCode
{
[XmlAttribute("codeLinework")]
public string codeLinework { get; set; }
[XmlElement("CodeAttributes")]
public List<CodeAttributes> codeAttributes { get; set; }
}
[XmlRoot("CodeAttributes")]
public class CodeAttributes
{
[XmlAttribute("attributeName")]
public string attributeName { get; set; }
[XmlAttribute("attributeType")]
public string attributeType { get; set; }
[XmlAttribute("valueType")]
public string valueType { get; set; }
[XmlAttribute("valueRegion")]
public string valueRegion { get; set; }
[XmlElement("text")]
public Text text { get; set; }
}
[XmlRoot("text")]
public class Text
{
[XmlElement("textChoiceList")]
public TextChoiceList textChoiceList { get; }
}
[XmlRoot("textChoiceList")]
public class TextChoiceList
{
[XmlElement("textList")]
public List<TextList> textList { get; set; }
}
[XmlRoot("textList")]
public class TextList
{
[XmlAttribute("textListValue")]
public string textListValue { get; set; }
}
Extract of the XML file I am deserializing.
<Code codeName="KERB" codeDesc="Kerbs" codeType="Point">
<PointCode codeLinework="open line">
<CodeAttributes attributeName="String" attributeType="Normal" valueType="Integer" valueRegion="None">
<integer />
</CodeAttributes>
<CodeAttributes attributeName="Type" attributeType="Normal" valueType="Text" valueRegion="ChoiceList">
<text>
<textChoiceList>
<textList textListValue="Square Kerb" />
<textList textListValue="Roll Kerb" />
</textChoiceList>
</text>
</CodeAttributes>
The missing setter for textChoiceList property in the Text class that leads to the text was null as the only property in the class is unable to set value.
So adding the missing setter to the property will solve the issue.
[XmlRoot("text")]
public class Text
{
[XmlElement("textChoiceList")]
public TextChoiceList textChoiceList { get; set; }
}
Sample .NET Fiddle

How to parse XML with several Attributes and an options list

I have an XML file that looks something similar to this:
<root>
<data label="product data" min="0" max="10">
<option>
<id>1</id>
<name>Name1</name>
</option>
<option>
<id>2</id>
<name>Name2</name>
</option>
<option>
<id>3</id>
<name>Name3</name>
</option>
</data>
</root>
I need to retreive both data attributes and the option list.
I tried this:
[XmlRoot(ElementName = "root")]
public class Data
{
// Retreive data attributes
[XmlElement(ElementName = "data")]
public Options Attributes { get; set; }
// Retrieve option list
[XmlArray("data")]
[XmlArrayItem("option", Type = typeof(GeneralOptions))]
public GeneralOptions[] Options { get; set; }
}
Optional classes:
Options
public class Options
{
[XmlAttribute("label")]
public string Label{ get; set; }
[XmlAttribute("min")]
public string Min{ get; set; }
[XmlAttribute("max")]
public string Max{ get; set; }
}
GeneralOptions
public class GeneralOptions
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "name")]
public string Name{ get; set; }
}
But when I try to deserialize the object, it launches the following exception:
The XML element 'data' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.
I imagine the problem is that I'm trying to retreive the same element "twice". But I need to retreive both things. I cannot use the [Attribute] thing because there are several Attributes to retreive, and I need to do this with several XML Elements with the same format and I want to reuse it.
So, how can I retreive both of them?
You'll need to restructure it slightly:
[XmlRoot("root")]
public class Data
{
[XmlElement("data")]
public OptionsData Options { get; set; }
}
public class OptionsData
{
[XmlAttribute("label")]
public string Label { get; set; }
[XmlAttribute("min")]
public string Min { get; set; }
[XmlAttribute("max")]
public string Max { get; set; }
[XmlElement("option")]
public List<GeneralOptions> Items { get; } = new List<GeneralOptions>();
}
public class GeneralOptions
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
}
I suggest using xmltocsharp or anyother tools to convert the XML to C# Models within seconds... (eliminates all manual mistakes)
As mentioned by #canton7, another easy method is using Visual Studio: Edit -> Paste Special -> Paste XML As Classes
[XmlRoot(ElementName="option")]
public class Option {
[XmlElement(ElementName="id")]
public string Id { get; set; }
[XmlElement(ElementName="name")]
public string Name { get; set; }
}
[XmlRoot(ElementName="data")]
public class Data {
[XmlElement(ElementName="option")]
public List<Option> Option { get; set; }
[XmlAttribute(AttributeName="label")]
public string Label { get; set; }
[XmlAttribute(AttributeName="min")]
public string Min { get; set; }
[XmlAttribute(AttributeName="max")]
public string Max { get; set; }
}
[XmlRoot(ElementName="root")]
public class Root {
[XmlElement(ElementName="data")]
public Data Data { get; set; }
}

Create a custom XML serializer in c# to help the xml doc get converted to object

I have a xml format in following format mentioned below:-
<JobRunnerPluginStaus PluginName="JobRun">
<JobstepStatus>
<JobStatus StepNumber="1" StepStatus="Done"/>
<JobStatus StepNumber="2" StepStatus="Started" />
</JobstepStatus>
</JobRunnerPluginStaus>
I want to get it converted to following class object using Generics and Reflection.
I want to convert the attributes to simple type(PluginName) and the nested property to a list object(JobstepStatus).
public class JobRunnerPluginStaus
{
public List<JobStatus> JobstepStatus { get; set; }
public string PluginName { get; set; }
}
public class JobStatus
{
public int StepNumber { get; set; }
public string StepStatus { get; set; }
}
I mostly use sites like: https://xmltocsharp.azurewebsites.net/
to do the dirty work for me.
Below is how your class hierarchy would look like:
[XmlRoot(ElementName="JobStatus")]
public class JobStatus {
[XmlAttribute(AttributeName="StepNumber")]
public string StepNumber { get; set; }
[XmlAttribute(AttributeName="StepStatus")]
public string StepStatus { get; set; }
}
[XmlRoot(ElementName="JobstepStatus")]
public class JobstepStatus {
[XmlElement(ElementName="JobStatus")]
public List<JobStatus> JobStatus { get; set; }
}
[XmlRoot(ElementName="JobRunnerPluginStaus")]
public class JobRunnerPluginStaus {
[XmlElement(ElementName="JobstepStatus")]
public JobstepStatus JobstepStatus { get; set; }
[XmlAttribute(AttributeName="PluginName")]
public string PluginName { get; set; }
}

Unable to Deserialize XML

I have the following code but unable to deserialize, can you see where I'm going wrong? It only catch the first record on the first array item.
[XmlRootAttribute("Booking")]
public class Reservation
{
[XmlArray("Included")]
[XmlArrayItem("Meals")]
public Meals[] Food { get; set; }
[XmlArrayItem("Drinks")]
public Drinks[] Drink { get; set; }
}
public class Meals
{
[XmlAttribute("Breakfast")]
public string Breakfast { get; set; }
[XmlAttribute("Lunch")]
public string Lunch { get; set; }
[XmlAttribute("Dinner")]
public string Dinner { get; set; }
}
public class Drinks
{
[XmlAttribute("Soft")]
public string Softs { get; set; }
[XmlAttribute("Beer")]
public string Beer { get; set; }
[XmlAttribute("Wine")]
public string Wine { get; set; }
}
Here's the associated XML
<?xml version="1.0" standalone="yes"?>
<Booking>
<Included>
<Meals
Breakfast="True"
Lunch="True"
Dinner="False">
</Meals>
<Drinks
Soft="True"
Beer="False"
Wine="False">
</Drinks>
</Included>
<Included>
<Meals
Breakfast="True"
Lunch="False"
Dinner="False">
</Meals>
<Drinks
Soft="True"
Beer="True"
Wine="True">
</Drinks>
</Included>
</Booking>
I'm a bit of a newbie so any help would be great, unfortunately after trawling through the many exmaples you already have online I still haven't been able to figure this out.
Use the following example and apply this syntax in ListItem array,
[XmlType("device_list")]
[Serializable]
public class DeviceList {
[XmlAttribute]
public string type { get; set; }
[XmlElement( "item" )]
public ListItem[] items { get; set; }
}
following link contains all the syntax & attributes
http://msdn.microsoft.com/en-us/library/2baksw0z.aspx
I see no obvious way your class structure could be matched to the XML document. The underlying organizations seem to be quite different.
The following class hierarchy could be easily deserialized from the XML document you provide (assuming your document covers the general case) :
[Serializable]
[XmlRoot("Booking")]
public class Booking : List<Included>
{
}
[Serializable]
public class Included
{
public Meals Meals { get; set; }
public Drinks Drinks { get; set; }
}
public class Meals
{
[XmlAttribute("Breakfast")]
public string Breakfast { get; set; }
[XmlAttribute("Lunch")]
public string Lunch { get; set; }
[XmlAttribute("Dinner")]
public string Dinner { get; set; }
}
public class Drinks
{
[XmlAttribute("Soft")]
public string Softs { get; set; }
[XmlAttribute("Beer")]
public string Beer { get; set; }
[XmlAttribute("Wine")]
public string Wine { get; set; }
}
Then, deserialization code would be : (serializedObject is the string containing your serialized object)
XmlSerializer ser = new XmlSerializer(typeof (string));
XmlReader reader = XmlTextReader.Create(new StringReader(serializedObject));
var myBooking = ser.Deserialize(reader) as Booking;

Categories

Resources