Complex XML deserialization in c# - c#

Here's my blob:
<Attributes>
<SomeStuff>...</SomeStuff>
<Dimensions>
<Weight units="lbs">123</Weight>
<Height units="in">123</Height>
<Width units="in">123</Width>
<Length units="in">123</Length>
</Dimensions>
</Attributes>
I'm trying to deserialize it using xml attributes on my class members, but I'm having trouble. I'm trying to use a "Dimensions" type with a unit and value. How do I get the unit as an attribute and get the value to the value?
Here's what I'm trying:
[Serializable]
public class Attributes
{
public object SomeStuff { get; set; } // Not really...
public Dimensions Dimensions { get; set; }
}
[Serializable]
public class Dimensions
{
public Dimension Height { get; set; }
public Dimension Weight { get; set; }
public Dimension Length { get; set; }
public Dimension Width { get; set; }
}
[Serializable]
public class Dimension
{
[XmlAttribute("units")]
public string Units { get; set; }
[XmlElement]
public decimal Value { get; set; }
}
I know that this code is expecting an actual "Value" element inside the dimension. But I can't find any attribute decorators in the .NET library that could tell it to use the actual text of the element for this, other than XmlText, but I want a decimal... Is a proxy field the only option? (e.g.
[XmlText] public string Text { get; set; }
[XmlIgnore]
public decimal Value
{
get { return Decimal.Parse(this.Text); }
set { this.Text = value.ToString("f2"); }
}
Thanks.

You can use XmlAttribute for the attribute, and XmlText for the text. So try changing your public decimal Value to be decorated with [XmlText].
[Serializable]
public class Dimension
{
[XmlAttribute("units")]
public string Units { get; set; }
[XmlText]
public decimal Value { 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

C# Xml deserialization Element in object property

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

XElement deserialization

I have a problem deserializing XElement.
Here is the xml code:
<phrase level="1">Where are <subject>you</subject> going?</phrase>
and this is the code for the class
[XmlRoot("phrase")]
public class Phrase
{
[XmlAttribute("level")]
public int Level { get; set; }
[XmlElement("subject")]
public string Subject { get; set; }
}
It's possible to get the text value of phrase TAG ("Where are going?") in deserialization?
I found my solution. It was easy, sorry!
My new class:
[XmlRoot("phrase")]
public class Phrase
{
[XmlAttribute("level")]
public int Level { get; set; }
[XmlElement("subject")]
public string Subject { get; set; }
[XmlText]
public string Value { get; set; }
}
...in Value field I can get XMLTAG text value!

C# Xml deserialization with custom type member

I have an object to deserialize but the object has custom type ApplicationLanguage that cannot be serialize.
[Serializable]
public class FieldTranslation
{
// how is this possible?
// does the 'en-us' in this member is reachable in this concept?
//public ApplicationLanguage Lang = ApplicationLanguagesList.Get("en-us");
//public ApplicationLanguage Lang { get; set; }
[XmlAttribute("name")]
public string Name{ get; set; }
public string Tooltip { get; set; }
public string Label { get; set; }
public string Error { get; set; }
public string Language { get; set; }
}
I built an API to get type ApplicationLanguage from the cache like that:
ApplicationLanguage en= ApplicationLanguagesList.Get("en-us");
Is there anyway that I can combine the custom type in the serialization above?
this is the xml:
<Fields lang="en-us">
<Item name="FirstName">
<Tooltip>Please provide your {0}</Tooltip>
<Error>{0} Is not valid</Error>
<Label>First Name</Label>
</Item>
</Fields>
you could change your class struct like
[Serializable]
[XmlRoot("Fields")]
public class FieldCollection
{
[XmlAttribute("lang")]
public string Lanuage { get; set; }
[XmlElement("Item")]
public FieldTranslation[] Fields { get; set; }
}
[Serializable]
public class FieldTranslation
{
[XmlAttribute("name")]
public string Name { get; set; }
public string Tooltip { get; set; }
public string Label { get; set; }
public string Error { get; set; }
public string Language { get; set; }
}
and then set the language property to serialize
Clarification: this answer is based on the pre-edit xml, where there was an
<Language>he</Language>
element. This answer does not apply to the <Fields lang="en-us"> scenario.
Something like:
[XmlIgnore]
public ApplicationLanguage Lang { get; set; }
[XmlElement("Language")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public string LangSerialized {
get { return Lang == null ? null : Lang.Name; } // or where-ever "he" comes from
set { Lang = value == null ? null : ApplicationLanguagesList.GetByName(value); }
}
Here the LangSerialized member is used as a proxy to the short-form of Lang. With XmlSerializer it is required that this member is public, but I've added a few other attributes to make it disappear from most other common usages.
You can manually fill a field in the collection above like this:
[XmlAttribute("lang")]
public string ManuallyFilledLang{ get; set; }
You also could implement a IXmlSerializable interface in your ApplicationLanguage class

Categories

Resources