Prepend parent node when serializing C# property - c#

I'd like to serialize the following class to xml:
public class Survey
{
[XmlElement("edit")]
public string EditLink { get; set; }
}
As expected this serializes as (removed extra stuff not important to the question)
<Survey><edit>http://example.com/editlink</edit></Survey>
However, I'd like to prepend a parent node to the edit node, so that the resultant xml is:
<Survey><links><edit>http://example.com/editlink</edit></links></Survey>
Is there a way to do this with just the serialization attributes, without modifying the structure of the class?

You can't with that structure. If you expose EditLink as a collection then you can:
public class Survey
{
[XmlArray("links")]
[XmlArrayItem("edit")]
public string[] edit
{
get
{
return new [] {EditLink};
}
set
{
EditLink = value[0];
}
}
[XmlIgnore]
public string EditLink { get; set; }
}
Which yields:
<Survey>
<links>
<edit>http://example.com/editlink</edit>
</links>
</Survey>

You can try using the XMLSerializer class.
public class Survey
{
public string EditLink { get; set; }
}
private void SerializeSurvey()
{
XmlSerializer serializer = new XmlSerializer(typeof(Survey));
Survey survey = new Survey(){EditLink=""};
// Create an XmlTextWriter using a FileStream.
Stream fs = new FileStream(filename, FileMode.Create);
XmlWriter writer = new XmlTextWriter(fs, Encoding.Unicode);
// Serialize using the XmlTextWriter.
serializer.Serialize(writer, survey);
writer.Close();
}

Related

XML serializing node as parent class incorrectly instead of child

I am serializing a class that is incorrectly creating the node of one of its properties. my class structure is as follows:
Here is the top class i am serializing
[DataContract]
public class XmlReportConfiguration
{
[DataMember]
[XmlArrayItem(nameof(SingleValueDescription), typeof(SingleValueDescription))]
[XmlArrayItem(nameof(MultiValueDescription), typeof(MultiValueDescription))]
public List<Description> Descriptions { get; set; }
}
MultiValueDescription inherits from SingleValueDescription which inherits from Description.
Description has the XMlInclude tag for both the single and multi value description
My issue is when i go to serialize a Description that is of type MultiValueDescription , the xml node is serializing it as SingleValueDescription.
If i remove the XmlArrayItem Entry for the SingleValueDescription from the XmlReportConfiguration class, it then works as I want it to, but I cant remove that declaration for obvious reasons.
Is there some tag/declaration I'm missing here that is causing the serializer to ignore the child class for the node and use the parent class?
Here is the method when creating the serializer:
public static string SerializeReportConfiguration(XmlReportConfiguration config)
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlReportConfiguration));
StringBuilder sb = new StringBuilder();
using (TextWriter writer = new StringWriter(sb))
{
serializer.Serialize(writer, config);
}
return sb.ToString();
}
public static XmlReportConfiguration DeserializeReportConfiguration(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlReportConfiguration));
using (StringReader reader = new StringReader(xml))
{
XmlReportConfiguration sessionConfig = serializer.Deserialize(reader) as XmlReportConfiguration;
return sessionConfig;
}
}
Found a solution. The polymorphism causes issues when serializing. In my report config I used a list of the following new class and it solved my issues.
[DataContract]
public class SerializableDescription : IXmlSerializable
{
#region Properties
public SerializableDescription()
{
}
public SerializableDescription(Description description)
{
Description = description;
}
[DataMember]
public Description Description { get; set; }
#endregion
#region Methods
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
string typeStr = reader.GetAttribute("Type");
Type type = TypeCache.GetTypeEx(typeStr);
XmlSerializer ser = new XmlSerializer(type);
reader.ReadStartElement();
Description = (Description)ser.Deserialize(reader);
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
Type type = Description.GetType();
writer.WriteAttributeString("Type", type.FullName);
XmlSerializer ser = new XmlSerializer(type);
ser.Serialize(writer, Description);
}
#endregion
}

How to in general convert classes to xml nodes?

I want some Generic way to convert objects to xml nodes :
if i have some xml nodes like this:
<BusinessObject xmlns="http://xmlns.oracle.com/bpm/bpmobject/Data/BusinessObject"><?xml version="1.0" encoding="utf-16"?>
<BusinessObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<attribute1>sss</attribute1>
<attribute2>sss</attribute2>
</BusinessObject></BusinessObject>
I convert it to Json like that
{
"-xmlns": "http://xmlns.oracle.com/bpm/bpmobject/Data/BusinessObject",
"#text": "<?xml version=\"1.0\" encoding=\"utf-16\"?>
<BusinessObject xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<attribute1>sss</attribute1>
<attribute2>sss</attribute2>
</BusinessObject>"
}
Then to c# class:
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}
Now how to reverse it to xml nodes again after setting its value ? I want a general solution not for this example
XML serialization is what you are looking for
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}
public static void Main(string[] args)
{
Rootobject details = new Rootobject();
details.xmlns = "myNamespace";
details.text = "Value";
Serialize(details);
}
static public void Serialize(Rootobject details)
{
XmlSerializer serializer = new XmlSerializer(typeof(Rootobject));
using (TextWriter writer = new StreamWriter(#"C:\Xml.xml"))
{
serializer.Serialize(writer, details);
}
}
You can use XML Serialization for converting a Class to XML, and viceversa.
For reference, read C# Tutorial - XML Serialization.
You can also refer to XML Schema Definition Tool
Example:
[DataContract]
public class MyClass1 {
[DataMember]
public string name;
[DataMember]
public int age;
}
Serialize / Deserialize
MyClass1 obj = new MyClass1();
DataContractSerializer dcs = new DataContractSerializer(typeof(MyClass1));
using (Stream stream = new FileStream(#"C:\tmp\file.xml", FileMode.Create, FileAccess.Write))
{
using (XmlDictionaryWriter writer =
XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
{
writer.WriteStartDocument();
dcs.WriteObject(writer, obj);
}
}
I think you need to apply the Serializable attribute to your class to be able to serialize it. This makes sure that your class does not use some none serializable attributes.
[Serializable]
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}

How to deserealize a List of custom object?

This is my Model class:
public class ModelClass
{
public ModelClass()
{
}
public ModelClass(string operationName)
{
OperationName = operationName;
}
public string OperationName { get; set; }
public int Count { get; set; }
}
I have to serialize a list of this model class to a database table:
The table schema is:
ModelObjectContent (the serialized string)
IDModel
The method wich I use to serialize:
public static string SerializeObject(this List<ModelClass> toSerialize)
{
var xmlSerializer = new XmlSerializer(toSerialize.GetType());
var textWriter = new StringWriter();
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
When I save it to the database the string generated is like this:
<ArrayOfChartModel>
<ModelClass>
<OperationName>Chart1</OperationName>
<Count >1</Count>
</ModelClass>
<ModelClass>
<OperationName>Chart2</OperationName>
<Count >2</Count>
</ModelClass>
//etc
</ArrayOfChartModel>
The framework automattically creates a tag named ArrayOfChartModel and thats ok,
but my question is:
How to deserealize this xml to a list of ModelClass again?
This should work for you:
public static List<ModelClass> Deserialize(string xml)
{
var xmlSerializer = new XmlSerializer(typeof(ModelClass));
using (TextReader reader = new StringReader(xml))
{
return(List<ModelClass>)xmlSerializer.Deserialize(reader);
}
}

Parse XML list to typed object using annotations

I have this xml that return of a web service:
<return>
<LuckNumber>
<Number>00092</Number>
<CodError>00</CodError>
<Serie>019</Serie>
<Number>00093</Number>
<CodError>00</CodError>
<Serie>019</Serie>
<Number>00094</Number>
<CodError>00</CodError>
<Serie>019</Serie>
<Number>00095</Number>
<CodError>00</CodError>
<Serie>019</Serie>
</LuckNumber>
How Can I parse this XML to a typed object using annotations?
I Tried it, but doesn't work:
protected T ProccessResult<T>(string result) {
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(result))
{
var resultDeserialize = (T)(serializer.Deserialize(reader));
return resultDeserialize;
}
}
ProccessResult<List<GenerateNumberList>>(STRING_XML_ABOVE)
CLASS TO PARSE:
[XmlRoot("LuckNumber")]
public class GenerateNumberResult
{
[XmlElement("Number")]
public string LuckNumber { get; set; }
[XmlElement("CodError")]
public string CodError{ get; set; }
[XmlElement("Serie")]
public string Serie { get; set; }
}
Can someone help me? Thanks!
The root of your XML is the "return" element. Add a wrapper class that contains your list:
[XmlRoot("return")]
public class ResultWrapper
{
[XmlElement("LuckNumber")]
public List<GenerateNumberResult> numberList;
}
And get the result:
ResultWrapper result = ProccessResult<ResultWrapper>(xml);

Why does not XmlSerializer recognize this attribute?

I have a simple class with two properties:
[XmlRoot("response")]
public class Response
{
[XmlAttribute("code")]
string Code { get; set; }
[XmlAttribute("message")]
string Message { get; set; }
}
I try to deserialize an XML string with XmlSerializer:
static void Main(string[] args)
{
string xml = "<response code=\"a\" message=\"b\" />";
using(var ms = new MemoryStream())
using(var sw = new StreamWriter(ms))
{
sw.Write(xml);
sw.Flush();
ms.Position = 0;
XmlSerializer ser = new XmlSerializer(typeof(Response));
ser.UnknownAttribute += new XmlAttributeEventHandler(ser_UnknownAttribute);
var obj = ser.Deserialize(ms);
}
}
static void ser_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
throw new NotImplementedException();
}
The UnknownAttribute event gets fired at the code attribute, it does not get deserialized.
What is the reason for this? Am I using the XmlAttributeAttribute wrong?
This is because the attributes are not public in your class:
[XmlRoot("response")]
public class Response
{
[XmlAttribute("code")]
public string Code { get; set; }
[XmlAttribute("message")]
public string Message { get; set; }
}
From the documentation of XmlAttributeAttribute (emphasis is mine):
You can assign the XmlAttributeAttribute only to public fields or public properties that return a value (or array of values) that can be mapped to one of the XML Schema definition language (XSD) simple types (including all built-in datatypes derived from the XSD anySimpleType type).

Categories