Remove namespace from DataContract doesn't work - c#

I have to two simple serialize/desirialize methods,
Mapping:
[System.Runtime.Serialization.DataContract(Namespace = "", Name = "PARAMS")]
public sealed class CourseListRequest {
[DataMember(Name = "STUDENTID")]
public int StudentId { get; set; }
[DataMember(Name = "YEAR")]
public string Year { get; set; }
[DataMember(Name = "REQUESTTYPE")]
public int RequestType { get; set; }
}
public static string Serialize<T>(this T value) {
if (value == null) throw new ArgumentNullException("value");
try {
var dcs = new DataContractSerializer(typeof (T));
string xml;
using (var ms = new MemoryStream()) {
dcs.WriteObject(ms, value);
xml = Encoding.UTF8.GetString(ms.ToArray());
}
return xml;
}
catch (Exception e) {
throw;
}
}
public static T Deserialize<T>(this string xml) where T : class {
if (string.IsNullOrEmpty(xml)) {
return default(T);
}
try {
var dcs = new DataContractSerializer(typeof (T));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml))) {
ms.Position = 0;
return dcs.ReadObject(ms) as T;
}
}
catch (Exception e) {
throw;
}
}
result:
<PARAMS xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><REQUESTTYPE>36</REQUESTTYPE><STUDENTID>0</STUDENTID><YEAR>תשע</YEAR></PARAMS>
How to remove xmlns:i="http://www.w3.org/2001/XMLSchema-instance" ?? On serializing

Switch to using XmlSerializer
System.Xml.Serialization.XmlSerializer
This will generate plain XML with no namespaces

Related

Issue with Deserialization with xml

I am getting error with deserialization. It says error in xml document.
public T XmlDeserialiseResponseObject<T>(string xml)
{
T returnedXmlClass;
try
{
xml = XmlResponseObjectCleaner(xml);
var doc = new XmlDocument();
doc.LoadXml(xml);
var reader = new XmlNodeReader(doc.DocumentElement);
var ser = new XmlSerializer(typeof(T));
returnedXmlClass = (T)ser.Deserialize(reader);
}
catch (Exception ex)
{
throw ex;
}
return returnedXmlClass;
}
My XML :
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/elope/'><soap:Body><GetBenefitStatusFault xmlns:ns2='http://schemas.somesite.co.za/somesite/some/' schemaVersion='1.0'>
<ErrorCode>3513</ErrorCode>
<ErrorMessage>Membership details not valid: Match on initial not found</ErrorMessage>
</GetBenefitStatusFault></soap:Body></soap:Envelope>
XmlResponseObjectCleaner:
private string XmlResponseObjectCleaner(string xml)
{
var sb = new StringBuilder();
sb.Append(xml);
sb.Replace(#"""", "'");
sb.Replace("<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>", "");
sb.Replace("</env:Envelope>", "");
sb.Replace("<env:Header/>", "");
sb.Replace("<env:Body>", "");
sb.Replace("ns3:", "");
sb.Replace("ns2:", "");
sb.Replace("</env:Body>", "");
sb.Replace("env", "");
sb.Replace("T00:00:00.000+02:00", "");
sb.Replace("T00:00:00.000Z", "");
return sb.ToString();
}
You could:
load the XML into a DOM and pick out the Body element and parse the OuterXml from there
start at the envelope
Here's an approach for 2:
using System.IO;
using System.Xml.Serialization;
static class P
{
static void Main()
{
const string xml = #"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/elope/'><soap:Body><GetBenefitStatusFault xmlns:ns2='http://schemas.somesite.co.za/somesite/some/' schemaVersion='1.0'>
<ErrorCode>3513</ErrorCode>
<ErrorMessage>Membership details not valid: Match on initial not found</ErrorMessage>
</GetBenefitStatusFault></soap:Body></soap:Envelope>";
var obj = XmlDeserialiseResponseObject<GetBenefitBody>(xml);
if (obj.GetBenefitStatusFault is Fault f)
{
System.Console.WriteLine(f.ErrorCode);
System.Console.WriteLine(f.ErrorMessage);
}
}
public static T XmlDeserialiseResponseObject<T>(string xml)
{
var ser = new XmlSerializer(typeof(Envelope<T>));
var obj = (Envelope<T>)ser.Deserialize(new StringReader(xml));
return obj.Body;
}
}
[XmlRoot("Envelope", Namespace = "http://schemas.xmlsoap.org/soap/elope/")]
public class Envelope<T>
{
public T Body { get; set; }
}
public class GetBenefitBody
{
[XmlElement(Namespace = "")]
public Fault GetBenefitStatusFault { get; set; }
}
public class Fault
{
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
}

Deserialize xml into a list

I have a normal list based in model like:
Model:
public class ProjectHistoryModel
{
public int JobNumber { get; set; }
public int DesignKey { get; set; }
public string ProjectName { get; set; }
}
In class I have a list of this model like:
public List<ProjectHistoryModel> ProjectHistoryModel = new List<ProjectHistoryModel>();
Then I save that list into xml file as:
Serialize list:
public static string SerializeObject<T>(this T value)
{
if (value == null)
{
return string.Empty;
}
try
{
var xmlserializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var writer = XmlWriter.Create(stringWriter))
{
xmlserializer.Serialize(writer, value);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
throw new Exception("An error occurred", ex);
}
}
So I save list just sending it to that method as:
var historyXml = ProjectHistoryModel.SerializeObject();
XML.HistoryProjects = historyXml;
XML.SaveXML();
Now my question is: How can I deserialize this xml and convert to a list again?
I try it something like this but I get stuck:
public static List<string> Load()
{
var xmlList = XML.HistoryProjects;
using (var stream = System.IO.File.OpenRead(FileName))
{
var serializer = new XmlSerializer(xmlList));
return serializer.Deserialize(stream) as [xmlList];
}
}
Regards
You just need to do the same thing in reverse, using a StringReader instead of a writer.
public static T DeserializeObject<T>(this string source)
{
if (string.IsNullOrEmpty(source))
{
return default(T);
}
try
{
var xmlserializer = new XmlSerializer(typeof(T));
var stringReader = new StringReader(source);
using (var reader = XmlReader.Create(stringReader))
{
var result = xmlserializer.Deserialize(reader);
return (T)result;
}
}
catch (Exception ex)
{
throw new Exception("An error occurred", ex);
}
}
Then call it with:
var input = new List<ProjectHistoryModel>();
var serialized = input.SerializeObject();
var output = serialized.DeserializeObject<List<ProjectHistoryModel>>();
Here is a link to a working example on DotNetFiddle.

How to create xml with attribute using XmlSerializer?

I'm working on xml generation using list to direct xml of generic class, but getting wrong result of xml.
I want below output from XmlSerializer.
<root>
<rating city="A" code="A1">A++</rating>
<rating city="B" code="A2">A</rating>
<rating city="C" code="A3">AB</rating>
</root>
currently i'm getting this
<ratings reason="reason123">
<rating>R</rating>
</ratings>
<ratings reason="reason123">
<rating>R</rating></ratings>
C# Code
public class root
{
[XmlAttribute("city")]
public string city { get; set; }
[XmlAttribute("code")]
public string code { get; set; }
[XmlElement("rating")]
public string rating { get; set; }
}
string tempXML6 = XmlExtensions.Serialize(rootList)
static public void Serialize(object classobject)
{
XmlSerializer SerializedObject = new XmlSerializer(classobject.GetType());
using (MemoryStream xmlStream = new MemoryStream())
{
SerializedObject.Serialize(xmlStream, classobject);
xmlStream.Position = 0;
//Loads the XML document from the specified string.
XmlDocument resultDocument = new XmlDocument();
resultDocument.Load(xmlStream);
if (!string.IsNullOrEmpty(resultDocument.DocumentElement.InnerXml))
{
return resultDocument.DocumentElement.InnerXml;
}
else
{
return string.Empty;
}
}
}
please let me know what's needs to be change.
Your object model is wrong. It should be something like this.
[XmlRoot("root")]
public class Root
{
[XmlElement("rating")]
public Rating[] Ratings { get; set; }
}
public class Rating
{
[XmlAttribute("city")]
public string City { get; set; }
[XmlAttribute("code")]
public string Code { get; set; }
[XmlText]
public string Value { get; set; }
}
To serialize the object do this
Root root = new Root
{
Ratings = new Rating[]
{
new Rating { City = "A", Code = "A1", Value = "A++" },
new Rating { City = "B", Code = "A2", Value = "A" },
new Rating { City = "C", Code = "A3", Value = "AB" }
}
};
string serializedObject = Serialize(root);
This is the serialize method
public static string Serialize<T>(T item)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringWriter stringWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
{
serializer.Serialize(xmlWriter, item, new XmlSerializerNamespaces(new[] { new XmlQualifiedName(string.Empty, string.Empty) }));
}
return stringWriter.ToString();
}
}
Xml output
<root>
<rating city="A" code="A1">A++</rating>
<rating city="B" code="A2">A</rating>
<rating city="C" code="A3">AB</rating>
</root>
Please Change your Class defination to like this:
[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class root
{
private rootRating[] ratingField;
[XmlElementAttribute("rating")]
public rootRating[] rating
{
get
{
return this.ratingField;
}
set
{
this.ratingField = value;
}
}
}
[XmlTypeAttribute(AnonymousType = true)]
public partial class rootRating
{
private string cityField;
private string codeField;
private string valueField;
[XmlAttributeAttribute()]
public string city
{
get
{
return this.cityField;
}
set
{
this.cityField = value;
}
}
[XmlAttributeAttribute()]
public string code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
[XmlTextAttribute()]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
//try this
public static XElement SerializeRoot(IEnumerable<root> objRoot)
{
XElement serializedRoot = null;
using (MemoryStream memoryStream = new MemoryStream())
{
using (TextWriter StreamWriter = new StreamWriter(memoryStream))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<root>));
xmlSerializer.Serialize(StreamWriter, objRoot);
serializedRoot = XElement.Parse(Encoding.UTF8.GetString(memoryStream.ToArray()));
}
}
return serializedRoot;
}

My nested Class collection XMLRoot name is not being used when serializing to xml

I have a Model populated and I wish to serlise to an xml document.
Due to naming conventions I have to over ride the class names for my XML document,
This is my Model(s):
[Serializable]
[XmlRoot("preferences")]
public class PreferencesModel
{
[XmlIgnore]
public string MessageToUser { get; set; }
[XmlElement(ElementName = "sectiondivider")]
public List<SectionDivider> SectionDivider { get; set; }
}
[Serializable]
[XmlRoot(ElementName = "sectiondivider")]
public class SectionDivider
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("preference")]
public List<PreferenceModel> PreferenceModel { get; set; }
}
[Serializable]
[XmlRoot("preference")]
public class PreferenceModel
{
[XmlAttribute("type")]
public string Type { get; set; }
public string Name { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
[XmlElement("options")]
public List<Option> Options { get; set; }
}
this is how I serialize:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(ObjectToXmlString(obj, includeNameSpace, includeStartDocument, rootAttribute));
return xDoc;
public static string ObjectToXmlString(Object obj, bool includeNameSpace, bool includeStartDocument, XmlRootAttribute rootAttribute)
{
SpecialXmlWriter stWriter = null;
XmlSerializer xmlSerializer = default(XmlSerializer);
string buffer = null;
try
{
if (rootAttribute == null)
{
xmlSerializer = new XmlSerializer(obj.GetType());
}
else
{
xmlSerializer = new XmlSerializer(obj.GetType(), rootAttribute);
}
MemoryStream memStream = new MemoryStream();
StringWriter writer = new StringWriter();
stWriter = new SpecialXmlWriter(memStream, new UTF8Encoding(false), includeStartDocument);
if (!includeNameSpace)
{
System.Xml.Serialization.XmlSerializerNamespaces xs = new XmlSerializerNamespaces();
//To remove namespace and any other inline
//information tag
xs.Add("", "");
xmlSerializer.Serialize(stWriter, obj, xs);
}
else
{
xmlSerializer.Serialize(stWriter, obj);
}
buffer = Encoding.UTF8.GetString(memStream.ToArray());
}
catch (Exception e)
{
string msg = e.Message;
throw;
}
finally
{
if (stWriter != null)
stWriter.Close();
}
return buffer;
}
I call it like this:
XmlDocument preferencesxml = Codec.ObjectToXml(m.SectionDivider,false,
false, new XmlRootAttribute("preferences"));
My m value is:
and my resulting XML is this:
XmlRootAttribute, as the name suggests, only applies to the root element of the XML being serialised.
You need to use XmlTypeAttribute in this context:
[XmlType("sectiondivider")]`
public class SectionDivider
{
//...
}
As an aside, the [Serializable] attribute is not relevant to XmlSerializer - it can be removed unless you need it for some other purpose.

Avoid duplicated code in XML serializable classes

I have two Serializable classes with very similar code. Actually, except for the part where specific constructor is called, serialization code is identical.
Is there a way to create a common class to contain the common parts, so that specific classes (subclasses?) can implement only the constructor part? I can think of generics, factory pattern, but could not figure out how to do it.
// Fictitious classes
[Serializable]
public class FlightParameters {
public double MaxHeight { get; set; }
pulbic double MaxSpeedKmPerHour { get; set; }
public static FlightParameters Load(String fname) {
FlightParameters result;
using (var fs = new FileStream(fname, FileMode.OpenOrCreate)) {
var serializer = new XmlSerializer(typeof(FlightParameters));
try {
result = (FlightParameters)serializer.Deserialize(fs);
}
// catch "file not found"
catch (InvalidOperationException) {
result = new FlightParameters() {
MaxHeight = 30000;
MaxSpeedKmPerHour = 1500;
}
serializer.Serialize(fs, result);
}
return result;
}
}
}
[Serializable]
public class SailingParameters {
public double MaxDepth { get; set; }
pulbic double MaxSpeedKnots { get; set; }
public static SailingParameters Load(String fname) {
SailingParameters result;
using (var fs = new FileStream(fname, FileMode.OpenOrCreate)) {
var serializer = new XmlSerializer(typeof(SailingParameters));
try {
result = (SailingParameters)serializer.Deserialize(fs);
}
// catch "file not found"
catch (InvalidOperationException) {
result = new SailingParameters() {
MaxDepth = 13000;
MaxSpeedKnots = 15;
}
serializer.Serialize(fs, result);
}
return result;
}
}
}
Usage:
FlightParameters _fparam = FlightParameters.Load(somePath);
SailingParameters _sparam = SailingParameters.Load(someOtherPath);
The easiest way I can see to do that would be something like:
static class XmlUtils {
public static T Load<T>(string filename, Func<T> onMissing = null)
where T : class, new()
{
using (var fs = File.OpenRead(filename)) {
var serializer = new XmlSerializer(typeof(T));
try {
return (T)serializer.Deserialize(fs);
} catch (InvalidOperationException) { // catch "file not found"
return onMissing == null ? new T() : onMissing();
}
}
}
}
allowing something like;
public static SailingParameters Load(string filename) {
return XmlUtils.Load<SailingParameters>(filename, () => new SailingParameters {
MaxDepth = 13000;
MaxSpeedKnots = 15;
});
}

Categories

Resources