C# serializer not adding prefix to root element - c#

Seen lots of people with this same issue and no answers anywhere, so answering it myself here;
When serializing an XML class that should have a prefix attached to it, the prefix is missing.
[XmlRoot(ElementName = "Preadvice", Namespace = "http://www.wibble.com/PreadviceRequest")]
public class Preadvice
{
}
var XMLNameSpaces = new XmlSerializerNamespaces();
XMLNameSpaces.Add("isd", "http://www.wibble.com/PreadviceRequest");
And this is my serializing method;
public static string SerializeStandardObject<T>(T obj, XmlSerializerNamespaces ns, XmlAttributeOverrides xao, XmlRootAttribute xra)
{
XmlSerializer serializer = new XmlSerializer(typeof(T), (xao == null ? new XmlAttributeOverrides() : xao), new Type[] { obj.GetType() }, (xra == null ? new XmlRootAttribute(obj.GetType().Name) : xra), "");
using (StringWriter sw = new StringWriter())
{
using (System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(sw))
{
serializer.Serialize(writer, obj, (ns == null ? new XmlSerializerNamespaces() : ns));
}
return sw.ToString();
}
}
This produces;
<?xml version="1.0" encoding="utf-16"?>
<Preadvice xmlns:isd="http://www.wibble.com/PreadviceRequest">
</Preadvice>
Which is missing the prefix, it should look like this..
<?xml version="1.0" encoding="utf-16"?>
<isd:Preadvice xmlns:isd="http://www.wibble.com/PreadviceRequest">
</isd:Preadvice>

If your serializer includes an xmlrootattribute when it is created, it doesn't apply namespaces you have specified manually, and therefore misses the "isd" tag off the first element. The easiest fix is to remove the xmlrootattribute;
public static string SerializeStandardObject<T>(T obj, XmlSerializerNamespaces ns)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringWriter sw = new StringWriter())
{
using (System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(sw))
{
serializer.Serialize(writer, obj, (ns == null ? new XmlSerializerNamespaces() : ns));
}
return sw.ToString();
}
}

Related

XML Serialization Missing Some Elements

following is the part of my xml serializing object.
private decimal tOAMOUNTField;
public decimal TOAMOUNT
{
get
{
return this.tOAMOUNTField;
}
set
{
this.tOAMOUNTField = value;
}
}
XmlSerializer xsSubmit = new XmlSerializer(typeof(MyClassObject));
var entity = new Myobject();
entity .TOAMOUNT = 2.22M;
using (StringWriter sww = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sww))
{
// sww.WriteLine(#"<?xml version=""1.0"" encoding=""UTF-8""?>");
xsSubmit.Serialize(writer , entity);
output = sww.ToString();
}
}
above mention "ToAmount" Property is not serializing in XML
Kindly point out the mistake because all other properties are serializing
You are initializing a XmlSerializer object with type MyClassObject.
XmlSerializer xsSubmit = new XmlSerializer(typeof(MyClassObject));
But are serializing a 'Myobject()' object.
Try changing it in:
XmlSerializer xsSubmit = new XmlSerializer(typeof(Myobject));

C#: How to shorten that XML appending?

I have that XML file which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<backupatmail>
<backup id="0">
<foldername>TestFolder</foldername>
<backupdate>09/10/2015</backupdate>
<comment>Sample comment text is here</comment>
<numberofparts>7</numberofparts>
<lastsucceed>Test.007</lastsucceed>
</backup>
<backup id="1">
<foldername>TestFolder2</foldername>
<backupdate>09/10/2015</backupdate>
<comment>Sample comment text is here</comment>
<numberofparts>15</numberofparts>
<lastsucceed>Test.015</lastsucceed>
</backup>
</backupatmail>
Now, I want to append new node(?):
<backup id="999">
<foldername>testing1</foldername>
<backupdate>99/99/9999</backupdate>
</backup>
I wrote following code:
public static void AddBackupToXML()
{
XmlDocument doc = new XmlDocument();
doc.Load(GlobalSettings.appDefaultFolder + "backups.xml");
XmlElement backupNodeNew = doc.CreateElement("backup");
XmlAttribute backupId = doc.CreateAttribute("id");
backupId.Value = "999";
backupNodeNew.Attributes.Append(backupId);
XmlNode nodeTitle = doc.CreateElement("foldername");
nodeTitle.InnerText = "testing1";
XmlNode nodeUrl = doc.CreateElement("backupdate");
nodeUrl.InnerText = "99/99/9999";
backupNodeNew.AppendChild(nodeTitle);
backupNodeNew.AppendChild(nodeUrl);
doc.DocumentElement.AppendChild(backupNodeNew);
doc.Save(GlobalSettings.appDefaultFolder + "backups.xml");
}
Is there any shorten way to do that and also keep simplicity at beginners level?
I will recommend you to use LINQ to XML. It has more simple API for working with XML and your code will look like
var file_name = GlobalSettings.appDefaultFolder + "backups.xml";
XDocument xdoc = XDocument.Load(file_name);
var backup999 = new XElement("backup",
new XAttribute("id", 999),
new XElement("foldername", "testing1"),
new XElement("backupdate", "99/99/9999")
);
xdoc.Root.Add(backup999);
xdoc.Save(file_name);
How I did it plenty of times, using copy special feature of visual studio http://blog.codeinside.eu/2014/09/08/Visual-Studio-2013-Paste-Special-JSON-And-Xml/ I generated the classed describing the xml structure, handle it really clean and easy from code and transfomed when required with System.Xml.Serialization https://support.microsoft.com/en-us/kb/815813 in xml doc or whatever was the need.
The same way from xml to c# object https://msdn.microsoft.com/en-us/library/fa420a9y(v=vs.110).aspx.
My personal preference is to not use the xml api directly. Rather, use the model object then serialize and de-serialize it. It's much cleaner in my opinion and the code to do what you actually need is only 3 lines once your have the generic serializer in place.
What you can do is de-serialize your object into an actual "backupatmail" object and then call backupatmail.BackUpItems.Add(your new item here) and then deserialize it back into a string.
This approach is slower than using LinqToXml during runtime but most of the time a extra millisecond or more isn't a big deal.
Here's the serialization/ deserialization code.
using System.Xml;
using System.Xml.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
public class SerializationUtils
{
public static T Deserialize<T>(string data)
{
XmlSerializer objSerializer = new XmlSerializer(typeof(T));
using (var reader = new StringReader(data))
{
return (T)objSerializer.Deserialize(reader);
}
}
public static string Serialize<T>(T obj)
{
XmlSerializer objSerializer = new XmlSerializer(typeof(T));
XmlSerializerNamespaces emptyNamespaces = new XmlSerializerNamespaces(new [] { XmlQualifiedName.Empty });
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Auto;
#if DEBUG
settings.Indent = true;
#else
settings.Indent = false;
#endif
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
objSerializer.Serialize(writer, obj, emptyNamespaces);
return stream.ToString();
}
}
}
and for your use.
string mailItems = GetXmlStringFromSomewhere();
var objMail = SerializationUtils.Deserialize<BackUpMail>(mailItems);
var newItem = new BackUp() { FolderName = "testing1", BackupDate = DateTime.Now};
objMail.BackUpItems.Add(newItem);
var strMailWAddedItem = SerializationUtils.Serialize(objMail);
Here are your entity classes.
public class BackUpMail
{
public List<BackUp> BackUpItems {get;set;}
}
public class BackUp
{
[XmlAttribute("id")]
public string ID {get;set}
[XmlElement("foldername")]
public string FolderName {get;set;}
[XmlElement("backupdate")]
public DateTime BackupDate {get;set;}
[XmlElement("comment")]
public string Comment {get;set}
[XmlElement("numberofparts")]
public string NumberOfParts {get;set}
[XmlElement("lastsucceed")]
public string LastSucceed {get;set}
}
Since you have the code, just parameterize it.
public static void someOtherMethod(){
XmlDocument doc = new XmlDocument();
doc.Load(GlobalSettings.appDefaultFolder + "backups.xml");
// some loop..
doc.DocumentElement.AppendChild(createNode(id[i], foldername[i], backupdate[i]));
doc.Save(GlobalSettings.appDefaultFolder + "backups.xml");
}
public static void createNode(string id, string foldername, string backupdate)
{
XmlElement backupNodeNew = doc.CreateElement("backup");
XmlAttribute backupId = doc.CreateAttribute("id");
backupId.Value = id;
backupNodeNew.Attributes.Append(backupId);
XmlNode nodeTitle = doc.CreateElement("foldername");
nodeTitle.InnerText = foldername;
XmlNode nodeUrl = doc.CreateElement("backupdate");
nodeUrl.InnerText = backupdate;
backupNodeNew.AppendChild(nodeTitle);
backupNodeNew.AppendChild(nodeUrl);
return backupNodeNew;
}

How to serialize List<T> to XML Document.?

I'm not experienced in XML-serialization. I need to serialize System.Collections.Generic.List to XML document. I have the following classes:
public class Person
{
public string Name;
public string Phone;
public Int32 Score;
}
[Serializable()]
public class PersonOperation:Person
{
public String City;
public String OperationType;
public DateTime OperationDate;
public Decimal Amount;
public Decimal AmountEUR;
public void RoubleToEuro(CurrencyCode p_CurrencyCode, Decimal p_CurrencyRate)
{
if (p_CurrencyCode == CurrencyCode.Euro)
{
this.AmountEUR = Decimal.Round(Amount / p_CurrencyRate, 2);
}
}
}
I have a collection of PersonOperation instances that I must serialize to XML.
private List<PersonOperation> _depositorsOperationsList = new List<PersonOperation>();
For XML serialization I try to use the following method:
public XmlDocument GetEntityXml<T>()
{
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attr = new XmlAttributes();
attr.XmlRoot = new XmlRootAttribute("Operation");
overrides.Add(typeof(List<T>), attr);
XmlDocument xmlDoc = new XmlDocument();
XPathNavigator nav = xmlDoc.CreateNavigator();
using (XmlWriter writer = nav.AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
ser.Serialize(writer, _depositorsOperationsList);
}
return xmlDoc;
}
I'm in need of the following XML-format after serialization:
<?xml version="1.0" encoding="Windows-1251" ?>
<Operation>
<PersonOperation>
<Name>John Smith</Name>
<Phone>79161234586</Phone>
<City>Glasgow</City>
<Date>2014-02-03</Date>
<OperationType>Join</OperationType>
<Amount>9000.00</Amount>
<AmountEUR>144.06</AmountEUR>
</PersonOperation>
<PersonOperation>
<Name>Bill Satly</Name>
<Phone>79163214569</Phone>
<City>London</City>
<Date>2014-07-10</Date>
<OperationType>Join</OperationType>
<Amount>9000.00</Amount>
<AmountEUR>144.06</AmountEUR>
</PersonOperation>
. . . . . . . . . . .
<Operation>
But instead of this format I have the following one-line horror:
<Operation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><PersonOperation><Name>John Smith</Name><Phone>79161234586</Phone><Score>270</Score><City>Glasgow</City><OperationType>Join</OperationType><OperationDate>2014-02-03</OperationDate><Amount>9000.0000</Amount><AmountEUR>144.06</AmountEUR></PersonOperation><PersonOperation><Name>Bill Satly</Name><Phone>79163214569</Phone><Score>270</Score><City>London</City><OperationType>Join</OperationType><OperationDate>2014-07-10</OperationDate><Amount>9000.0000</Amount><AmountEUR>144.06</AmountEUR></PersonOperation></Operation>
How can I repair my GetEntityXml method for correct XML-format?
The XmlWriter has a Settings property of type XmlWriterSettings.
Try using that to specify the formatting to be used.
using (XmlWriter writer = nav.AppendChild())
{
writer.Settings.Indent = true;
XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
ser.Serialize(writer, _depositorsOperationsList);
}
More information here:
https://msdn.microsoft.com/en-us/library/kbef2xz3(VS.80).aspx
If you open your file with special XML editor or just with web navigator like chrome or internet explorer it will look like you want.
Just pasting snippet from my code that works fine..
Public Function ToXmlString() As String
Dim builder = New StringBuilder()
Dim xmlSerializer = New XmlSerializer(GetType(List(Of T)), New XmlRootAttribute(_rootNodeName))
Using writer = XmlWriter.Create(builder, New XmlWriterSettings() With {.OmitXmlDeclaration = True})
xmlSerializer.Serialize(writer, _source)
End Using
Return builder.ToString()
End Function
---- Converted C# Code ----
public string ToXmlString()
{
var builder = new StringBuilder();
var xmlSerializer = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(_rootNodeName));
using (writer = XmlWriter.Create(builder, new XmlWriterSettings { OmitXmlDeclaration = true })) {
xmlSerializer.Serialize(writer, _source);
}
return builder.ToString();
}
where _rootNodeName is name of your root node of xml and _source is sourceList
And then to create XMLDoc from string --
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlString);

remove type declaration from XML while serialize

I need to get clear xml without any namespace and type declarations. Here is the serialized xml:
<placeBetRequest p1:type="PlaceBetRequestTeamed" xmlns:p1="http://www.w3.org/2001/XMLSchema-instance">
...
</placeBetRequest>
Need to someway configure XmlSerializer to set it don't add any attributes but only mine (if I set them with [XmlAttribte]
the clean xml need to looks like this:
<placeBetRequest>
...
</placeBetRequest>
Here is my serialization method:
public static string XmlConvert<T>(T obj, params Type[] wellKnownTypes) where T : class
{
var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var settings = new XmlWriterSettings {Indent = true, OmitXmlDeclaration = true};
XmlSerializer serializer = wellKnownTypes == null
? new XmlSerializer(typeof(T))
: new XmlSerializer(typeof(T), wellKnownTypes);
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, obj, emptyNamepsaces);
return stream.ToString();
}
}
Please help. Thanks.
I've been using regex
string input =
"<p1:placeBetRequest p1:type=\"PlaceBetRequestTeamed\" xmlns:p1=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"</p1:placeBetRequest>";
string pattern = #"(?'prefix'\</?)(?'ns'[^:]*:)";
string output = Regex.Replace(input, pattern, "${prefix}");

XML Serialization of List<T> - XML Root

First question on Stackoverflow (.Net 2.0):
So I am trying to return an XML of a List with the following:
public XmlDocument GetEntityXml()
{
StringWriter stringWriter = new StringWriter();
XmlDocument xmlDoc = new XmlDocument();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
List<T> parameters = GetAll();
serializer.Serialize(xmlWriter, parameters);
string xmlResult = stringWriter.ToString();
xmlDoc.LoadXml(xmlResult);
return xmlDoc;
}
Now this will be used for multiple Entities I have already defined.
Say I would like to get an XML of List<Cat>
The XML would be something like:
<ArrayOfCat>
<Cat>
<Name>Tom</Name>
<Age>2</Age>
</Cat>
<Cat>
<Name>Bob</Name>
<Age>3</Age>
</Cat>
</ArrayOfCat>
Is there a way for me to get the same Root all the time when getting these Entities?
Example:
<Entity>
<Cat>
<Name>Tom</Name>
<Age>2</Age>
</Cat>
<Cat>
<Name>Bob</Name>
<Age>3</Age>
</Cat>
</Entity>
Also note that I do not intend to Deserialize the XML back to List<Cat>
There is a much easy way:
public XmlDocument GetEntityXml<T>()
{
XmlDocument xmlDoc = new XmlDocument();
XPathNavigator nav = xmlDoc.CreateNavigator();
using (XmlWriter writer = nav.AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("TheRootElementName"));
ser.Serialize(writer, parameters);
}
return xmlDoc;
}
If I understand correctly, you want the root of the document to always be the same, whatever the type of element in the collection ? In that case you can use XmlAttributeOverrides :
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attr = new XmlAttributes();
attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
overrides.Add(typeof(List<T>), attr);
XmlSerializer serializer = new XmlSerializer(typeof(List<T>), overrides);
List<T> parameters = GetAll();
serializer.Serialize(xmlWriter, parameters);
A better way to the same thing:
public XmlDocument GetEntityXml<T>()
{
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attr = new XmlAttributes();
attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
overrides.Add(typeof(List<T>), attr);
XmlDocument xmlDoc = new XmlDocument();
XPathNavigator nav = xmlDoc.CreateNavigator();
using (XmlWriter writer = nav.AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
List<T> parameters = GetAll<T>();
ser.Serialize(writer, parameters);
}
return xmlDoc;
}
so simple....
public static XElement ToXML<T>(this IList<T> lstToConvert, Func<T, bool> filter, string rootName)
{
var lstConvert = (filter == null) ? lstToConvert : lstToConvert.Where(filter);
return new XElement(rootName,
(from node in lstConvert
select new XElement(typeof(T).ToString(),
from subnode in node.GetType().GetProperties()
select new XElement(subnode.Name, subnode.GetValue(node, null)))));
}

Categories