C# XML Serialization of Attribute - c#

I have some XML which I would like to serialize into a class.
<MasterData>
<Data>
<SomeInnerData>
some inner data
</SomeInnerData>
</Data>
</MasterData>
<MoreData>
<SubMoreData>moredate</SubMoreData>
</MoreDate>
and
[System.SerializableAttribute()]
public class MasterData
{
public string SomeInnnerData {get;set;}
public string SubMoreDate {get;set;}
}
How do I set the string member variables to serialize the appropriate data in the XML? My issue arises in that the element is not a child of the MasterData element.

The simplest way is to work backwards, get your class setup to serialize into the format you want, so that you can deserialize into it with ease.
Note: Your xml didn't validate, so I changed it to this for an example
<MasterData>
<Data>
<SomeInnerData>some inner data</SomeInnerData>
</Data>
<MoreData>
<SubMoreData>moredate</SubMoreData>
</MoreDate>
</MasterData>
Currently, your problem is that you have Data and MoreData elements that don't map to anything
You'd need to create classes like
public class MasterData {
public Data Data {get; set;}
public MoreData Data {get; set;}
}
public class Data {
public string SomeInnerData {get; set;}
}
public class MoreData {
public string SubMoreData {get; set;}
}
You can have your properties named other things, and use the [XmlElement(ElementName="SubMoreData")] to map the property, to the correct Element.
Or, you could implement the IXmlSerializable interface, and write custom serialization code in a single class to map your class to xml however you want

The XML example you provided is not valid XML thus you will not be able to directly serialize it. You need a root node for it work this way.
Such that:
<AllData>
<MasterData>
<Data>
<SomeInnerData>
some inner data
</SomeInnerData>
</Data>
</MasterData>
<MoreData>
<SubMoreData>moredate</SubMoreData>
</MoreDate>
<AllData>
[System.SerializableAttribute()]
public class AllData
{
public MasterData MasterData {get;set;}
public MoreData MoreData {get;set;}
}
[System.SerializableAttribute()]
public class Data
{
public string SomeInnnerData {get;set;}
}
[System.SerializableAttribute()]
public class MasterData
{
public string SomeInnnerData {get;set;}
}
[System.SerializableAttribute()]
public class MasterData
{
public Data Data {get;set;}
}
[System.SerializableAttribute()]
public class MoreData
{
public string SubMoreDate {get;set;}
}

Implement ixmlserializable for custom serialization

With the normal .NET XMLSerializer class, public properties are serialized by default. You have to explicitly attribute properties not to be serialized:
[System.Xml.Serialization.XmlIgnoreAttribute]
Here's the documentation: XmlSerializer
...
Now that you've revised your question, the answer is that you will no longer be able to use the XMLSerializer class. (Or you will have to have some intermediary class which matches the structure of your XML, to facilitate the serialization and deserialization.) If you have a very specific XML structure that you want transform arbitrarily, use an XmlReader.

How about using XSL to transform from/to the XML format that your C# class directly serializes to?

Related

Deserialize multiple XML elements have same name

i have an XML form look like this:
<Myset>
<element>1A</element>
<element>2B</element>
<element>3C</element>
<element>AB</element>
..........
<element>AA</element>
What should structure class, variables should i use to deserialize it. I want to read and update value of each element. I have try this, but it doesn't work:
public class Myset
{
public List<string> element {get; set;}
// or public string[] element { get; set; }
}
XmlElementAttribute will allow you specify element name.
public class case_id_list
{
[XmlElement("case_id")]
public List<string> case_id {get; set;}
}
You should use this service. It converts your xml structure to valid c# model structure. It's a very useful tool.
*In case you ever want to convert your JSON to C# this is another useful service.
Cheers!

How to Deserialize XML elements to generic list with unknown element names

I am retrieving and successfully deserializing an xml string from a database table column for the known element names (these do not change) but there are also some nested XML Elements called "Other Attributes" which are not always going to be known. I'm having some trouble deserialising these unknown element names to a generic list so I can display them in html once deserialised.
The XML is as follows:
<Detail>
<DetailAttributes>
<Name>Name_123</Name>
<Type>Type_123</Type>
</DetailAttributes>
<OtherAttributes>
<SummaryKey AttributeName="SummaryKey">SummaryKey_123</SummaryKey>
<Account AttributeName="Account">Account_123</Account>
</OtherAttributes>
</Detail>
I have no problem deserialising the 'Name' and 'Type' elements and I can deserialise the 'SummaryKey' and 'Account' elements but only if I explicitly specify their element names - which is not the desired approach because the 'OtherAttributes' are subject to change.
My classes are as follows:
[XmlRoot("Detail")]
public class objectDetailsList
{
[XmlElement("DetailAttributes"), Type = typeof(DetailAttribute))]
public DetailAttribute[] detailAttributes { get; set; }
[XmlElement("OtherAttributes")]
public List<OtherAttribute> otherAttributes { get; set; }
public objectDetailsList()
{
}
}
[Serializable]
public class Detail Attribute
{
[XmlElement("Type")]
public string Type { get;set; }
[XmlElement("Name")]
public string Name { get;set; }
public DetailAttribute()
{
}
}
[Serializable]
public class OtherAttribute
{
//The following will deserialise ok
//[XmlElement("SummaryKey")]
//public string sumKey { get; set; }
//[XmlElement("Account")]
//public string acc { get; set; }
//What I want to do below is create a list of all 'other attributes' without known names
[XmlArray("OtherAttributes")]
public List<Element> element { get; set; }
}
[XmlRoot("OtherAttributes")]
public class Element
{
[XmlAttribute("AttributeName")]
public string aName { get; set; }
[XmlText]
public string aValue { get; set; }
}
When I try to retrieve the deserialised list of OtherAttribute elements the count is zero so it's not able to access the elements nested within "Other Attributes".
Can anybody help me with this please?
With concrete classes and dynamic data like this, you won't be able to lean on the standard XmlSerializer to serialize / deserialize for you - as it reflects on your classes, and the properties you want to populate simply don't exist. You could provide a class with all possible properties if your set of 'OtherAttributes' is known and finite, and not subject to future change, but that would give you an ugly bloated class (and I think you've already decided this is not the solution).
Practical options therefore:
Do it manually. Use the XmlDocument class, load your data with .Load(), and iterate the nodes using .SelectNodes() using an XPath query (something like "/Detail/OtherAttributes/*"). You will have to write the lot yourself, but this gives you complete control over the serialization / deserialization. You won't have to cover your code in (arguably superfluous!) attributes either.
Use Json.NET (http://james.newtonking.com/json), it allows for far greater control over serialization and deserialization. It's fast, has good docs and is overall pretty nifty really.

how to serialize class objects to xml document

I hope to find a solution from you. What I need is to serialize ValidatorList class object into an xml document. How to do this?
I tried like this:
XmlSerializer _serializer = new XmlSerializer(list);
But I don't know how to make output of xml for list that has several classes.
C#
_list= new ListVal();
Type _type = typeof(ras);
_list.Add(new RequiredField
{
Property = _type.GetProperty("CustRef")
}.Add(new AsciiVal()));
_list.Add(new RequiredField
{
Property = _type.GetProperty("ctr")
}.Add(new StringLengthVal
{
min= 3,
max= 3
}));
[Serializable]
public class Field
{
public Field Next
{
get;
set;
}
public Field TypeName
{
get;
set;
}
public Field PropertyName
{
get;
set;
}
}
public class RequiredField : Field
{
//TODO
}
public class AsciiVal: Field
{
//TODO
}
public class StringLengthVal: Field
{
//TODO
}
public class ListVal: List<Field>
{
//TODO
}
I have something close, but not exactly the Xml you want. In actual fact I think you'll see that the Xml produced below makes a bit more sense than what you have.
To get you started, you control the serialization and deserialization using attributes in the System.Xml.Serialization namespace. A few useful ones to read up on are
XmlRootAttribute
XmlElementAttribute
XmlAttributeAttribute
XmlIncludeAttribute
So I mocked up some code which closely matches your own. Notice the addition of some attributes to instruct the serializer how I want the Xml to be laid out.
[XmlInclude(typeof(AsciiValidator))]
[XmlInclude(typeof(RequiredValidator))]
[XmlInclude(typeof(StringLengthValidator))]
public class FieldValidator
{
[XmlElement("Next")]
public FieldValidator Next
{
get;
set;
}
[XmlElement("PropertyName")]
public string PropertyName
{
get;
set;
}
}
public class AsciiValidator: FieldValidator
{
}
public class RequiredValidator: FieldValidator
{
}
public class StringLengthValidator: FieldValidator
{
[XmlElement]
public int MinLength{get;set;}
[XmlElement]
public int MaxLength{get;set;}
}
[XmlRoot("ValidatorList")]
public class ValidatorList : List<FieldValidator>
{
}
Point of interest; Every class inheriting FieldValidator must be added to the list of known types using XmlIncludeAttribute so the serializer knows what to do with them)
Then I created an example object map:
var test = new ValidatorList();
test.Add(
new RequiredValidator()
{
PropertyName="CustRef",
Next = new AsciiValidator()
});
test.Add(
new RequiredValidator()
{
PropertyName="CurrencyIndicator",
Next = new StringLengthValidator(){
MinLength=3,
MaxLength = 10
}
});
Finally I told the serializer to serialize it (and output the result to the console)
var ser = new XmlSerializer(typeof(ValidatorList));
ser.Serialize(Console.Out,test);
This was the result:
<?xml version="1.0" encoding="utf-8"?>
<ValidatorList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FieldValidator xsi:type="RequiredValidator">
<Next xsi:type="AsciiValidator" />
<PropertyName>CustRef</PropertyName>
</FieldValidator>
<FieldValidator xsi:type="RequiredValidator">
<Next xsi:type="StringLengthValidator">
<MinLength>3</MinLength>
<MaxLength>10</MaxLength>
</Next>
<PropertyName>CurrencyIndicator</PropertyName>
</FieldValidator>
</ValidatorList>
Not a million miles away from what you wanted. There is the need to output certain things in a certain way (eg xsi:type tells the serializer how to deserialize back to the object map). I hope this gives you a good start.
Here is a live, working example: http://rextester.com/OXPOB95358
Deserialization can be done by calling the Deserialize method on the XmlSerializer.
For example, if your xml is in a string:
var ser = new XmlSerializer(typeof(ValidatorList));
var test = "<..../>" // Your Xml
var xmlReader = XmlReader.Create(new StringReader(test));
var validatorList = (ValidatorList)ser.Deserialize(xmlReader);
There are many overrides of Deserialize which take differing inputs depending if the data is in a Stream an existing reader, or saved to a file.
You have to decorate the class that contains the _validators field with the KonwnType attribute
[Serializable]
[KwownType(typeof(RequiredFieldValidator)]
[KwownType(typeof(AsciValidator)]
public class MySerialisableClass
I have several SO answers that detail how to serialize objects using XML. I'll provide links below.
However, since you're looking for a rather simple serialization of your object, you may want to read up on the DataContractSerializer. It's much less complicated than the old .NET 1.x XML Serialization.
Here's the list of SO answers:
Omitting all xsi and xsd namespaces when serializing an object in .NET?
XmlSerializer: remove unnecessary xsi and xsd namespaces
Suppress xsi:nil but still show Empty Element when Serializing in .Net
Using XmlAttributeOverrides on Nested Properties
Even though many of these have to do with XML serialization and namespaces, they contain complete examples of serializing an object to XML using .NET 1.x XML Serialization.

Custom Array Item Name for DTO

One of my clients has XML data he wants to send to a service we are creating. A sample message might look like:
<SomeRootElement>
<Dates>
<Date>2012-05-20T00:00:00</Date>
<Date>2012-05-21T00:00:00</Date>
</Dates>
</SomeRootElement>
I have a corresponding type defined as a DataContract on my WCF service application:
[DataContract]
public class SomeRootElement {
[DataMember]
public ICollection<DateTime> Dates { get; set; }
}
The trouble is that based on this definition, WCF wants the Dates collection to look like:
<Dates>
<dateTime>2012-05-20T00:00:00</dateTime>
<dateTime>2012-05-21T00:00:00</dateTime>
</Dates>
Is there any way to influence the array item's serialized element name? This used to be easy using XML serialization attributes, but the DataContractSerializer ignores those.
This should do the trick:
[DataContract]
[KnownType(typeof(DateList))]
public class SomeRootElement {
[DataMember]
public ICollection<DateTime> Dates { get; set; }
}
[CollectionDataContract(ItemName="date")]
public class DateList : Collection<DateTime> {}
You are overriding the type it can use for deserializing the ICollection for a customized one.

DataContractSerializer not serializing one property

When I serialize the following class, the ContentPageId XML element is missing from the resulting XML file.
[CollectionDataContract(ItemName = "Widget")]
public sealed class StructurePage : List<Widget>, IEquatable<StructurePage>
{
[DataMember]
public int ContentPageId
{
get;
set;
}
public StructurePage(){}
public StructurePage(int pageId)
{
this.ContentPageId = pageId;
}
public bool Equals(StructurePage other)
{
return this.ContentPageId.Equals(other.ContentPageId);
}
}
Why is the property skipped when serializing and how to include it as XML element?
Is it possible to include it in serialization as an XML attribute to the StructurePage element? Was looking for this around the net but could find any info on it, apparently with XmlSerializer there was XmlAttributeAttribute attribute but no such thing with DataContractSerializer.
Go through this post http://social.msdn.microsoft.com/Forums/eu/wcf/thread/57eb195a-43a9-47fe-8b1a-a9d23feb2df2
According to this
Collection data contract classes cannot contain extra data members.
Hope this helps.

Categories