How to create xml with attribute using XmlSerializer? - c#

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

Related

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.

JSON format writing to file

I want to write my items by JSON format, but My files empty. Here is my two class:
public class DocPart
{
public string Title { get; set; }
public bool Checked { get; set; }
}
public class DocConfig
{
public List<DocPart> Parts { get; set; }
public static DocConfig LoadFromString(string jsonData)
{
var config = new DocConfig();
config.Parts = new List<DocPart>();
var part = new DocPart
{
Title = "chapter1",
"chapter2",
Checked = checkBox1.Checked,
checkbox2.Checked
};
config.Parts.Add(part);
var configString = config.SaveToString();
File.WriteAllText(#"C:\link to my file", configString);
var configString = File.ReadAllText(#"C:\link to my file");
var config = DocConfig.LoadFromString(configString);
foreach (var part in config.Parts)
{
if (part.Title == "chapter1")
chekbox1.Checked = part.Checked;
if (part.Title == "chapter2")
checkbox2.Checked = part.Checked;
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
var config = (DocConfig)serializer.ReadObject(ms);
return config;
}
}
public string SaveToString()
{
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream();
serializer.WriteObject(ms, this);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
So I run my program, everything looks okey, but my file is still empty without any JSON format data. Maybe you could help me?
Thanks.
public class DocPart
{
public string Title { get; set; }
public bool Checked { get; set; }
}
public class DocConfig
{
public List<DocPart> Parts { get; set; }
public static DocConfig LoadFromString()
{
var config = new DocConfig();
config.Parts = new List<DocPart>();
var part1 = new DocPart
{
Title = "chapter1",
Checked = checkBox1.Checked
};
config.Parts.Add(part1);
var part2 = new DocPart
{
Title = "chapter2",
Checked = checkBox2.Checked
};
config.Parts.Add(part2);
var configString = config.SaveToString();
File.WriteAllText(#"d:\temp\test.json", configString);
configString = File.ReadAllText(#"d:\temp\test.json");
var ms = new MemoryStream(Encoding.UTF8.GetBytes(configString));
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
config = (DocConfig)serializer.ReadObject(ms);
foreach (var part in config.Parts)
{
if (part.Title == "chapter1")
{
chekbox1.Checked = part.Checked;
Debug.WriteLine("chapter1" + part.Checked);
}
if (part.Title == "chapter2")
{
checkbox2.Checked = part.Checked;
Debug.WriteLine("chapter2" + part.Checked);
}
}
return config;
}
public string SaveToString()
{
var serializer = new DataContractJsonSerializer(typeof(DocConfig));
var ms = new MemoryStream();
serializer.WriteObject(ms, this);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
Here's a really simple example I mocked up for you...
void Main()
{
const string filePath = #"C:\FilePath\json.txt";
const string testJson = #"{""glossary"": {""title"": ""example glossary"", ""GlossDiv"": {""title"": ""S"", ""GlossList"": {""GlossEntry"": {""ID"": ""SGML"", ""SortAs"": ""SGML"", ""GlossTerm"": ""Standard Generalized Markup Language"", ""Acronym"": ""SGML"", ""Abbrev"": ""ISO 8879:1986"", ""GlossDef"": {""para"": ""A meta-markup language, used to create markup languages such as DocBook."", ""GlossSeeAlso"": [""GML"", ""XML""]}, ""GlossSee"": ""markup""}}}}}";
// Now we have our Json Object...
SampleJson sample = JsonConvert.DeserializeObject<SampleJson>(testJson);
// We convert it back into a string with indentation...
string jsonString = JsonConvert.SerializeObject(sample, Newtonsoft.Json.Formatting.Indented);
// Now simply save to file...
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(jsonString);
}
Process.Start(filePath);
}
// The following classes are what the `testJson` string is deserialized into.
public class GlossDef
{
[JsonProperty("para")]
public string Para { get; set; }
[JsonProperty("GlossSeeAlso")]
public string[] GlossSeeAlso { get; set; }
}
public class GlossEntry
{
[JsonProperty("ID")]
public string ID { get; set; }
[JsonProperty("SortAs")]
public string SortAs { get; set; }
[JsonProperty("GlossTerm")]
public string GlossTerm { get; set; }
[JsonProperty("Acronym")]
public string Acronym { get; set; }
[JsonProperty("Abbrev")]
public string Abbrev { get; set; }
[JsonProperty("GlossDef")]
public GlossDef GlossDef { get; set; }
[JsonProperty("GlossSee")]
public string GlossSee { get; set; }
}
public class GlossList
{
[JsonProperty("GlossEntry")]
public GlossEntry GlossEntry { get; set; }
}
public class GlossDiv
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("GlossList")]
public GlossList GlossList { get; set; }
}
public class Glossary
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("GlossDiv")]
public GlossDiv GlossDiv { get; set; }
}
public class SampleJson
{
[JsonProperty("glossary")]
public Glossary Glossary { get; set; }
}

XmlSerializer with custom namespace

I want to consume a restful web service with xml. I have to create this template in order to create a valid request:
<WS_IN_GetAccountCredit xmlns="http://schemas.datacontract.org/2004/07/WcfWebService">
<GetAccountCreditParams>
<Password>String content</Password>
<UserName>String content</UserName>
</GetAccountCreditParams>
<WSIdentity>
<WS_PassWord>String content</WS_PassWord>
<WS_UserName>String content</WS_UserName>
</WSIdentity>
</WS_IN_GetAccountCredit>
My serializer method is like this:
XmlSerializerNamespaces xmlNameSpace = new XmlSerializerNamespaces();
xmlNameSpace.Add("", "http://schemas.datacontract.org/2004/07/WcfWebService");
XmlSerializer xmlSerializer = new XmlSerializer(instance.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, instance, xmlNameSpace); ; return textWriter.ToString();
}
My output looks like this:
<?xml version="1.0" encoding="utf-16"?>
<WS_IN_GetAccountCredit xmlns:xmlns="http://schemas.datacontract.org/2004/07/WcfWebService">
<WSIdentity>
<WS_UserName>String content</WS_UserName>
<WS_PassWord>String content</WS_PassWord>
</WSIdentity>
<GetAccountCreditParams>
<UserName>String content</UserName>
<Password>String content</Password>
</GetAccountCreditParams>
</WS_IN_GetAccountCredit>
As you can see, the namespace and xml version is in wrong format. I also found this, this and this article but non of them could solve my problem.
How can create a valid request?
Here we go:
[XmlRoot(ElementName = "WS_IN_GetAccountCredit", Namespace = "http://schemas.datacontract.org/2004/07/WcfWebService")]
public class WS_IN_GetAccountCredit
{
private WS_IN_WebServiceIdentity wsIdentity;
private WS_IN_GetAccountCreditParams getAccountCreditParams;
public WS_IN_WebServiceIdentity WSIdentity { set { this.wsIdentity = value; } get { return this.wsIdentity; } }
public WS_IN_GetAccountCreditParams GetAccountCreditParams
{
set { this.getAccountCreditParams = value; }
get { return this.getAccountCreditParams; }
}
}
public class WS_IN_WebServiceIdentity
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class WS_IN_GetAccountCreditParams
{
public string UserName { get; set; }
public string Password { get; set; }
}
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("", "http://schemas.datacontract.org/2004/07/WcfWebService");
var ser = new XmlSerializer(typeof(WS_IN_GetAccountCredit));
using (var writer = new StringWriter())
{
ser.Serialize(writer, new WS_IN_GetAccountCredit
{
GetAccountCreditParams = new WS_IN_GetAccountCreditParams { Password = "pass", UserName = "use" },
WSIdentity = new WS_IN_WebServiceIdentity { Password = "pass", UserName = "use" }
},
namespaces);
var xml = writer.ToString();
}
The result is:
<?xml version="1.0" encoding="utf-16"?>
<WS_IN_GetAccountCredit xmlns="http://schemas.datacontract.org/2004/07/WcfWebService">
<WSIdentity>
<UserName>use</UserName>
<Password>pass</Password>
</WSIdentity>
<GetAccountCreditParams>
<UserName>use</UserName>
<Password>pass</Password>
</GetAccountCreditParams>
</WS_IN_GetAccountCredit>

Remove namespace from DataContract doesn't work

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

How to map an object to an existing XML file in C# .NET?

I have this existing XML file serving as a template with NO data, just simple nodes... here's a sample:
<?xml version="1.0" encoding="utf-8" ?>
<catalog>
<cd>
<title />
<artist />
<country />
<company />
<price />
<year />
</cd>
</catalog>
Now I have created a similar class for it.
public class Cd
{
public string Title { get; set; }
public string Artist { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Price { get; set; }
public string Year { get; set; }
}
The purpose is this:
Put values on the properties of the var cd = new Cd(); object
Get the existing XML file (template) then pass the values in it (like mapping the object to the existing XML)
Transform the XML template(with values) into XSLT to become HTML
I think that's all.
How to properly do this?
Thanks a lot!
You can use serialization to achieve (1) and (2)
[Serializable]
public class Cd
{
public string Title { get; set; }
public string Artist { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Price { get; set; }
public string Year { get; set; }
}
now in order to create an xml from an object use:
public static string SerializeObject<T>(this T obj)
{
var ms = new MemoryStream();
var xs = new XmlSerializer(obj.GetType());
var xmlTextWriter = new XmlTextWriter(ms, Encoding.UTF8);
xs.Serialize(xmlTextWriter, obj);
string serializedObject = new UTF8Encoding().GetString((((MemoryStream)xmlTextWriter.BaseStream).ToArray()));
return serializedObject;
}
in order to create an object from XML use:
public static T DeserializeObject<T>(this string xml)
{
if (xml == null)
throw new ArgumentNullException("xml");
var xs = new XmlSerializer(typeof(T));
var ms = new MemoryStream(new UTF8Encoding().GetBytes(xml));
try
{
new XmlTextWriter(ms, Encoding.UTF8);
return (T)xs.Deserialize(ms);
}
catch
{
return default(T);
}
finally
{
ms.Close();
}
}
I would create class:
class catalog
{
public CD cd {get;set;}
}
Here is serialization and deserealization helper:
public class Xml
{
public static string Serialize<T>(T value) where T : class
{
if (value == null)
{
return string.Empty;
}
var xmlSerializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringWriter))
{
xmlSerializer.Serialize(xmlWriter, value);
return stringWriter.ToString();
}
}
public static T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (TextReader reader = new StringReader(xml))
{
result = (T) serializer.Deserialize(reader);
}
return result;
}
}
Simply call:
catalog catalogObject = Xml.Deserialize<catalog>(xmlCatalogString);
I suspect you also will need to put some attributes on properties like XmlElement(ElementName = "title") because it is case sensitive.
MSDN

Categories

Resources