C# Xml deserialization Element in object property - c#

I'm consuming a Web API, and i get an xml result:
<tarification cle="XXXX">
<gamme reference="refX">
<tarif formula="F100">44.84</tarif>
<tarif formula="F125">47.63</tarif>
<tarif formula="F150">57.34</tarif>
<tarif formula="F200">67.95</tarif>
<option name="indiv-acc">0.5</option>
<option name="rap-cor">6.06</option>
</gamme>
</tarification>
I use this model to deserialize :
[XmlRoot(ElementName = "tarification", Namespace="")]
public class TarifResponse
{
[XmlElement(ElementName = "gamme")]
public Gamme Gamme { get; set; }
}
public class Gamme
{
[XmlAttribute(AttributeName="reference")]
public string Name { get; set; }
[XmlElement(ElementName = "tarif")]
public Formula[] Formulas { get; set; }
[XmlElement(ElementName = "option")]
public Option[] Options { get; set; }
}
public class Formula
{
[XmlAttribute(AttributeName="formula")]
public string Name { get; set; }
// WRONG ATTRIBUTE.. but witch one ?
[XmlElement]
public Decimal Amount { get; set; }
}
public class Option
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
// WRONG ATTRIBUTE.. but witch one ?
[XmlElement]
public Decimal Amount { get; set; }
}
The TarifResponse object is created, all fields are filled, except the two amounts fields. I expect this is because the right xml should be:
<amount>5.5</amount>
inside tarif or option elements..
Is this format is deserializable ?
Is there a way to this with attribute ?
Is this even an acceptable xml format ?
thank you

The [XmlText] attribute will get the inner text of the node. You might need to use [XmlText(Type=typeof(decimal))] to get the number parsed.
public class Option
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlText]
public Decimal Amount { get; set; }
}

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; }
}

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;

Deserialize List Error

I have an XML and the content is
<Contracts>
<Contract EntryType="U" ID="401" GroupCode="1">
</Contract>
</Contracts>
and I have a class with a list of contracts
[XmlArray("Contracts")]
[XmlArrayItem("Contract", typeof(Contract))]
public List<Contract> Contracts { get; set; }
so when I try to Deserialize this, I got this error:
"There was an error reflecting property 'Contracts'."
Deserialization code:
XmlSerializer reader = new XmlSerializer(typeof(ContractPosting));
xml.Position = 0;
eContractXML = (Contract)reader.Deserialize(xml);
Here are the classes:
public partial class ContractPosting
{
[XmlArray("Contracts")]
[XmlArrayItem("Contract", typeof(Contract))]
public List<Contract> Contracts { get; set; }
}
public class Contract
{
[XmlAttribute(AttributeName = "ContractID")]
public System.Nullable<int> ContractID { get; set; }
[XmlAttribute(AttributeName= "PostingID")]
public string PostingID { get; set; }
public EntryTypeOptions? EntryType { get; set; }
}
Nullable types cannot be serialised as attributes.
You must either change the Contract class to not use Nullable for the XML attributes or change the XML to write these properties as an XML element.
Try this:
public class Contract {
[XmlAttribute(AttributeName = "ContractID")]
public int ContractID { get; set; }
[XmlAttribute(AttributeName= "PostingID")]
public string PostingID { get; set; }
public System.Nullable<EntryTypeOptions> EntryType { get; set; }
}
OR:
public class Contract {
public int? ContractID { get; set; }
[XmlAttribute(AttributeName= "PostingID")]
public string PostingID { get; set; }
public System.Nullable<EntryTypeOptions> EntryType { get; set; }
}
Since the root node is <Contracts>, try re-arranging your class to this:
[XmlRoot("Contracts")]
public class ContractPosting {
[XmlElement("Contract", typeof(Contract))]
public List<Contract> Contracts { get; set; }
}
When you use XmlArray and XmlArrayItem, they have to both be nested inside of something. But your current XmlArray tag is actually the root node of the XML file, so it needs to be an XmlRoot.
Demo: http://ideone.com/jBSwGx
thanks, the problem was the Nullable type and I solved in this way
[XmlIgnore]
public System.Nullable<int> ContractID { get; set; }
[XmlAttribute("ContractID")]
public int ContractIDxml {
get { return ContractID ?? 00; }
set { ContractID = value; }
}

Categories

Resources