Why is the XmlWriter always outputting utf-16 encoding? - c#

I have this extension method
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
but whenever I call this it has an encoding of utf-16 specified, ie <?xml version="1.0" encoding="utf-16"?>. What am I doing wrong?

Strings are UTF-16, so writing to a StringWriter will always use UTF-16. If that's not what you want, then use some other TextWriter derived class, with the encoding you like.

As far as I know, StringWriter class will always use UTF 16 encoding when serializing to string. You can write your own override class that accepts a different encoding:
public class StringWriterWithEncoding : StringWriter
{
private readonly Encoding _encoding;
public StringWriterWithEncoding()
{
}
public StringWriterWithEncoding(IFormatProvider formatProvider)
: base(formatProvider)
{
}
public StringWriterWithEncoding(StringBuilder sb)
: base(sb)
{
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider)
: base(sb, formatProvider)
{
}
public StringWriterWithEncoding(Encoding encoding)
{
_encoding = encoding;
}
public StringWriterWithEncoding(IFormatProvider formatProvider, Encoding encoding)
: base(formatProvider)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, Encoding encoding)
: base(sb)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
: base(sb, formatProvider)
{
_encoding = encoding;
}
public override Encoding Encoding
{
get { return (null == _encoding) ? base.Encoding : _encoding; }
}
}
So you can use this instead:
using(var stringWriter = new StringWriterWithEncoding( Encoding.UTF8))
{
...
}

as #john-saunders mentioned in his answer:
StringWriter will always use UTF-16
So i used MemoryStream for this purposes.
In my case i using windows-1251 encoding.
var xmlSstring = "";
using (var ms = new MemoryStream())
{
var encoding = Encoding.GetEncoding(1251);
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = encoding
};
using (var xmlTextWriter = XmlWriter.Create(ms, settings))
{
doc.Save(xmlTextWriter);
xmlString = encoding.GetString(ms.ToArray());
}
}

As the accepted answer says, StringWriter is UTF-16 (Unicode) by default and design. If you want to do it by getting a UTF-8 string in the end, there are 2 ways I can give you to get it done:
Solution #1 (not very efficient, bad practice, but gets the job done): Dump it to a text file and read it back in, delete the file (probably only suitable for small files, if you even want to do this at all - just wanted to show it could be done!)
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var xmlWriter = XmlWriter.Create("MyFile.xml", settings))
{
serializer.Serialize(xmlWriter, value);
}
XmlDocument xml = new XmlDocument();
xml.Load("MyFile.xml");
byte[] bytes = Encoding.UTF8.GetBytes(xml.OuterXml);
File.Delete("MyFile.xml");
return Encoding.UTF8.GetString(bytes);
}
Solution #2 (better, easier, more elegant solution!): Do it like you have it, using StringWriter, but use its Encoding property to set it to UTF-8:
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new UTF8StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
public class UTF8StringWriter : StringWriter
{
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}

You should derive a new class from StringWriter which has an overriden encoding property.

If you do not want to use a class that derives from StringWriter, then in your case, you could simply set the OmitXmlDeclaration to false and declare your own, just as I do below:
public static string Serialize<T>(this T value, string xmlDeclaration = "<?xml version=\"1.0\"?>") where T : class, new()
{
if (value == null) return string.Empty;
using (var stringWriter = new StringWriter())
{
var settings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = xmlDeclaration != null,
};
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
var xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(xmlWriter, value);
var sb = new StringBuilder($"{Environment.NewLine}{stringWriter}");
sb.Insert(0, xmlDeclaration);
return sb.ToString();
}
}

Related

Separate object fields into two files by serializing DataContract

I an using DataContractSerializer and i want to separate data of same object into multiple files.
[DataContract]
public class TestObj
{
[DataMember]
protected double field1 = 0.0;
[DataMember]
protected double field2 = 0.0;
}
Specifically I want to save field1 in one XML file and field2 in a different XML file. Is there any way to do that using data contract serialization?
This is how I am serializing currently:
DataContractSerializer serializaer = new DataContractSerializer(GetType(), null,
0x7FFFFFFF /*maxItemsInObjectGraph*/,
false /*ignoreExtensionDataObject*/,
true /*preserveObjectReferences : this is most important to me */,
null /*dataContractSurrogate*/);
var fs = File.Open(fName, FileMode.Create);
serializaer.WriteObject(fs, this);
fs.Dispose();
return true;
I can suggest using Custom Xml Writer paired with serializer.
public class CustomWriter : XmlTextWriter
{
public CustomWriter(TextWriter writer) : base(writer) { }
public CustomWriter(Stream stream, Encoding encoding) : base(stream, encoding) { }
public CustomWriter(string filename, Encoding encoding) : base(filename, encoding) { }
public List<string> FieldList { get; set; }
private string _localName;
public override void WriteStartElement(string prefix, string localName, string ns)
{
if (!FieldList.Contains(localName))
base.WriteStartElement(prefix, localName, ns);
else
_localName = localName;
}
public override void WriteString(string text)
{
if (!FieldList.Contains(_localName))
base.WriteString(text);
}
public override void WriteEndElement()
{
if (!FieldList.Contains(_localName))
base.WriteEndElement();
else
_localName = null;
}
}
Use it as follows:
var data = new TestObj();
var serializer = new DataContractSerializer(
typeof(TestObj), null, 0x7FFFFFFF, false, true, null);
using (var writer = new CustomWriter(Console.Out)) // Specify filename or stream instead
{
writer.Formatting = Formatting.Indented;
writer.FieldList = new List<string> { "field1", "field3" }; // Specify fields to ignore
serializer.WriteObject(writer, data);
}
Just specify a list of fields that should be ignored in the FieldList property.
Of course, with this way, the DataContractSerializer will intermediate create xml with all the elements contained in the class. And only after that our custom writer will filter them. But it will happen on the fly, very quickly and effectively.
Once you serialise the whole object you can then split it using Linq to XML.
Oh, I even found an example how to do it at How to Split an XML file into multiple XML Files.

Serialize/Deserialize class containing byte array property into XML

My data class that will be serialized into XML look like this:
[XmlType(TypeName = "SPCFileInfo")]
[Serializable]
public class SPCFileInfoProtocol
{
[XmlElement("CompanyCode")]
public string CompanyCode { get; set; }
[XmlElement("FileName")]
public string FileName { get; set; }
[XmlElement("FileVer")]
public int FileVer { get; set; }
[XmlElement("FileSize")]
public long FileSize { get; set; }
[XmlElement("CreatedOn")]
public DateTime CreatedOn { get; set; }
[XmlElement("LastUpdatedOn")]
public DateTime LastUpdatedOn { get; set; }
[XmlElement("FileBytes")]
public byte[] FileBytes { get; set; }
}
And here's my serialization utiltiy class
public static class XmlSerializer
{
public static string SerializeToString<T>(T item)
{
if (item == null)
{
return null;
}
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
settings.Indent = false;
settings.OmitXmlDeclaration = false;
using (StringWriter textWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
{
serializer.Serialize(xmlWriter, item);
}
return textWriter.ToString();
}
}
public static T DeserializeFromString<T>(string xmlString)
{
T item = default(T);
try
{
using (StringReader stringReader = new StringReader(xmlString))
{
System.Xml.Serialization.XmlSerializer xmlSerializer =
new System.Xml.Serialization.XmlSerializer(typeof(T));
item = (T)xmlSerializer.Deserialize(stringReader);
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
return item;
}
}
Serialization into XML works fine, but when I attempt to deserialize, I get the following exception:
XMLException: There is an error in XML document.
hexadecimal value 0x00, is an invalid character.
Upon investigation, I found out that certain character codes are not valid for XML document. Removing invalid characters is not an option since they constitute the bytes for a file.
My question is how do you serialize/deserialize a data class like above into XML without stripping invalid bytes? If this is not possible, what are some viable alternatives?
Edit: Upon request, here's the full stacktrace of the error
System.InvalidOperationException: There is an error in XML document
(1, 21933). ---> System.Xml.XmlException: '.', hexadecimal value 0x00,
is an invalid character. Line 1, position 21933. at
System.Xml.XmlTextReaderImpl.Throw(Exception e) at
System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) at
System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos,
Int32& outOrChars) at System.Xml.XmlTextReaderImpl.ParseText()
at System.Xml.XmlTextReaderImpl.ParseElementContent() at
System.Xml.XmlTextReaderImpl.Read() at
System.Xml.XmlTextReader.Read() at
System.Xml.XmlReader.ReadElementString() at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read2_SPCCommandProtocol(Boolean
isNullable, Boolean checkType) at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSPCCommandProtocol.Read3_SPCCommand()
--- End of inner exception stack trace --- at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader) at
NextSPCFileUpdater.Utilities.XmlSerializer.DeserializeFromString[T](String
xmlString) in C:\Source
Codes\SPC\nextspc-fileupdater\NextSPCFileUpdater\Utilities\XmlSerializer.cs:line
48
And here's the new version of deserialization
public static T DeserializeFromString<T>(string xmlString)
{
T item = default(T);
try
{
using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
System.Xml.Serialization.XmlSerializer xmlSerializer =
new System.Xml.Serialization.XmlSerializer(typeof(T));
item = (T)xmlSerializer.Deserialize(xmlTextReader);
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
return item;
}
As you've noticed, there are lots of characters that may not be present in an XML document. These can be included in your data, however, using the proper escape sequence.
The default settings of the XmlTextReader cause it to mishandle this -- I think it interprets the escape sequences prematurely, but I'm not precisely certain. If I recall correctly, the XmlSerializer will create an XmlTextReader to wrap the TextReader you pass it. To override that, you need to create one yourself, setting its Normalization property of the XmlTextReader to false.
Regardless of whether my recollection of the causes of the problem is correct, however, setting Normalization to false will solve your problem:
var xmlReader = new XmlTextReader(textReader) { Normalization = false };
Or rather, in your case:
using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
System.Xml.Serialization.XmlSerializer xmlSerializer =
new System.Xml.Serialization.XmlSerializer(typeof(T));
item = (T)xmlSerializer.Deserialize(xmlTextReader);
}
As an aside, most will find your code far more readable if you use some using directives:
using System.Xml;
using System.Xml.Serialization;
using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
item = (T)xmlSerializer.Deserialize(xmlTextReader);
}
Still more will find it more readable if you use var (though I have at least one colleague who disagrees):
using System.Xml;
using System.Xml.Serialization;
using (var stringReader = new StringReader(xmlString))
using (var xmlTextReader = new XmlTextReader(stringReader) { Normalization = false })
{
var xmlSerializer = new XmlSerializer(typeof(T));
item = (T)xmlSerializer.Deserialize(xmlTextReader);
}

Can Json.NET serialize to stream with Formatting?

When using Json.NET library, you can specify formatting when you are serialising to string, but I can't find this option when serialising directly to stream. Am I missing something?
The code for the two serialisation methods is as follows:
public static string Serialize(MyObject obj)
{
JsonSerializerSettings settings = GetJsonSerializerSettings();
return JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
}
public static void SerializeToStream(MyObject obj, Stream stream)
{
var serializer = JsonSerializer.Create(GetJsonSerializerSettings());
using (var sw = new StreamWriter(stream))
using (var jsonTextWriter = new JsonTextWriter(sw))
{
serializer.Serialize(jsonTextWriter, obj);
}
}
private static JsonSerializerSettings GetJsonSerializerSettings()
{
JsonSerializerSettings settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter>
{
new StringEnumConverter()
}
};
return settings;
}
I haven't tried it, but I'd expect it to be fine if you specify the formatting in the settings:
public static void SerializeToStream(MyObject obj, Stream stream)
{
var settings = GetJsonSerializerSettings();
settings.Formatting = Formatting.Indented;
var serializer = JsonSerializer.Create(settings);
using (var sw = new StreamWriter(stream))
using (var jsonTextWriter = new JsonTextWriter(sw))
{
serializer.Serialize(jsonTextWriter, obj);
}
}
(Or change GetJsonSerializerSettings in a similar way, of course.)

Convert an object to an XML string

I have got a class named WebserviceType I got from the tool xsd.exe from an XSD file.
Now I want to deserialize an instance of an WebServiceType object to a string.
How can I do this?
The MethodCheckType object has as params a WebServiceType array.
My first try was like I serialized it: with a XmlSerializer and a StringWriter (while serializing I used a StringReader).
This is the method in which I serialize the WebServiceType object:
XmlSerializer serializer = new XmlSerializer(typeof(MethodCheckType));
MethodCheckType output = null;
StringReader reader = null;
// catch global exception, logg it and throw it
try
{
reader = new StringReader(path);
output = (MethodCheckType)serializer.Deserialize(reader);
}
catch (Exception)
{
throw;
}
finally
{
reader.Dispose();
}
return output.WebService;
Edit:
Maybe I could say it in different words: I have got an instance of this MethodCheckType object an on the other hand I have got the XML document from which I serialized this object. Now I want to convert this instance into a XML document in form of a string. After this I have to proof if both strings (of XML documents) are the same. This I have to do, because I make unit tests of the first method in which I read an XML document into a StringReader and serialize it into a MethodCheckType object.
Here are conversion method for both ways.
this = instance of your class
public string ToXML()
{
using(var stringwriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(stringwriter, this);
return stringwriter.ToString();
}
}
public static YourClass LoadFromXMLString(string xmlText)
{
using(var stringReader = new System.IO.StringReader(xmlText))
{
var serializer = new XmlSerializer(typeof(YourClass ));
return serializer.Deserialize(stringReader) as YourClass ;
}
}
I realize this is a very old post, but after looking at L.B's response I thought about how I could improve upon the accepted answer and make it generic for my own application. Here's what I came up with:
public static string Serialize<T>(T dataToSerialize)
{
try
{
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringwriter, dataToSerialize);
return stringwriter.ToString();
}
catch
{
throw;
}
}
public static T Deserialize<T>(string xmlText)
{
try
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
catch
{
throw;
}
}
These methods can now be placed in a static helper class, which means no code duplication to every class that needs to be serialized.
public static string Serialize(object dataToSerialize)
{
if(dataToSerialize==null) return null;
using (StringWriter stringwriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(dataToSerialize.GetType());
serializer.Serialize(stringwriter, dataToSerialize);
return stringwriter.ToString();
}
}
public static T Deserialize<T>(string xmlText)
{
if(String.IsNullOrWhiteSpace(xmlText)) return default(T);
using (StringReader stringReader = new System.IO.StringReader(xmlText))
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
}
public static class XMLHelper
{
/// <summary>
/// Usage: var xmlString = XMLHelper.Serialize<MyObject>(value);
/// </summary>
/// <typeparam name="T">Kiểu dữ liệu</typeparam>
/// <param name="value">giá trị</param>
/// <param name="omitXmlDeclaration">bỏ qua declare</param>
/// <param name="removeEncodingDeclaration">xóa encode declare</param>
/// <returns>xml string</returns>
public static string Serialize<T>(T value, bool omitXmlDeclaration = false, bool omitEncodingDeclaration = true)
{
if (value == null)
{
return string.Empty;
}
try
{
var xmlWriterSettings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = omitXmlDeclaration, //true: remove <?xml version="1.0" encoding="utf-8"?>
Encoding = Encoding.UTF8,
NewLineChars = "", // remove \r\n
};
var xmlserializer = new XmlSerializer(typeof(T));
using (var memoryStream = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlserializer.Serialize(xmlWriter, value);
//return stringWriter.ToString();
}
memoryStream.Position = 0;
using (var sr = new StreamReader(memoryStream))
{
var pureResult = sr.ReadToEnd();
var resultAfterOmitEncoding = ReplaceFirst(pureResult, " encoding=\"utf-8\"", "");
if (omitEncodingDeclaration)
return resultAfterOmitEncoding;
return pureResult;
}
}
}
catch (Exception ex)
{
throw new Exception("XMLSerialize error: ", ex);
}
}
private static string ReplaceFirst(string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
}
This is my solution, for any list object you can use this code for convert to xml layout. KeyFather is your principal tag and KeySon is where start your Forech.
public string BuildXml<T>(ICollection<T> anyObject, string keyFather, string keySon)
{
var settings = new XmlWriterSettings
{
Indent = true
};
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement(keyFather);
foreach (var objeto in anyObject)
{
writer.WriteStartElement(keySon);
foreach (PropertyDescriptor item in props)
{
writer.WriteStartElement(item.DisplayName);
writer.WriteString(props[item.DisplayName].GetValue(objeto).ToString());
writer.WriteEndElement();
}
writer.WriteEndElement();
}
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Flush();
return builder.ToString();
}
}

XmlSerializer.Serialize Stripping the <xml> tag

I am trying to get communicate to a payment processor. When I use XmlSerializer.Serialize
on my object I get
<?xml version=\"1.0\" encoding=\"utf-16\"?>
<txn xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<ssl_merchant_id>xxxxxx</ssl_merchant_id>
<ssl_user_id>xxxxxx</ssl_user_id>
<ssl_pin>xxxxxx</ssl_pin>
<ssl_test_mode>True</ssl_test_mode>
<ssl_transaction_type>ccavsonly</ssl_transaction_type>
<ssl_card_number>4111111111111111</ssl_card_number>
<ssl_exp_date>0612</ssl_exp_date>
<ssl_avs_address>101 Main St.</ssl_avs_address>
<ssl_avs_zip>90210</ssl_avs_zip>
</txn>
Prior to using that method, I manually built the XML for testing and this worked:
<txn>
<ssl_merchant_id>xxxxxx</ssl_merchant_id>
<ssl_user_id>xxxxxx</ssl_user_id>
<ssl_pin>xxxxxx</ssl_pin>
<ssl_test_mode>True</ssl_test_mode>
<ssl_transaction_type>ccavsonly</ssl_transaction_type>
<ssl_card_number>4111111111111111</ssl_card_number>
<ssl_exp_date>0612</ssl_exp_date>
<ssl_avs_address>101 Main St.</ssl_avs_address>
<ssl_avs_zip>90210</ssl_avs_zip>
</txn>
How would I go about stripping out the <?xml version=\"1.0\" encoding=\"utf-16\"?> and xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> from the XML or not have the serializer generate it to begin with?
My object looks like:
[XmlRoot(ElementName="txn")]
public class AvsTransmission
{
[XmlElement]
public string ssl_merchant_id { get; set; }
[XmlElement]
public string ssl_user_id { get; set; }
[XmlElement]
public string ssl_pin { get; set; }
[XmlElement]
public string ssl_test_mode { get; set; }
[XmlElement]
public string ssl_transaction_type { get; set; }
[XmlElement]
public string ssl_card_number { get; set; }
[XmlElement]
public string ssl_exp_date { get; set; }
[XmlElement]
public string ssl_avs_address { get; set; }
[XmlElement]
public string ssl_avs_zip { get; set; }
}
My first answer was only half of the problem, you also have to remove the declaration as has been mentioned.
Here is an example:
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer cs = new XmlSerializer(typeof(Cat));
cs.Serialize(writer, new Cat { Lives = 9 }, names);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
var xml = sr.ReadToEnd();
The string xml now contains:
<cat><Lives>9</Lives></cat>
First function convert object to xml string, the second one convert object and write xml to file simultaneously.
public static string Serialize<T>(T obj)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
var writer = new StringWriter();
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
var xml = writer.ToString();
return xml;
}
public static void Serialize<T>(T obj, string filepath)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
var writer = new StreamWriter(filepath);
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
}
Actually I realized that code repeat yourself. In these methods, change only one thing which is writer object, so the code must be like below. In these way, you can easily use code just by changing writer object type.
public static string Serialize<T>(T obj)
{
var writer = new StringWriter();
Serialize<T>(obj,writer);
var xml = writer.ToString();
return xml;
}
public static void Serialize<T>(T obj, string filepath)
{
var writer = new StreamWriter(filepath);
Serialize<T>(obj,writer);
}
public static void Serialize<T>(T obj, TextWriter writer)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
}
Very similar to #payo's orignal answer:
If you want to remove the namespace you may also want to remove the version, to save you searching I've added that functionality so the below code will do both.
I've also wrapped it in a generic method as I'm creating very large xml files which are too large to serialize in memory so I've broken my output file down and serialize it in smaller "chunks":
public string XmlSerialize<T>(T entity) where T : class
{
// removes version
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
StringWriter sw = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
// removes namespace
var xmlns = new XmlSerializerNamespaces();
xmlns.Add(string.Empty, string.Empty);
xsSubmit.Serialize(writer, entity, xmlns);
return sw.ToString(); // Your XML
}
}
If you use XmlWriter there is a setting to omit the declaration
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.omitxmldeclaration.aspx
I'll work on an example, but that might be enough to get you going.
EDIT: Here's a sample that runs in LinqPad
string test = "test";
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream strm = new MemoryStream();
XmlWriter writer = XmlWriter.Create(strm, settings);
XmlSerializer serializer = new XmlSerializer(typeof(string));
serializer.Serialize(writer, test);
strm.Position = 0;
StreamReader reader = new StreamReader(strm);
var x = reader.ReadToEnd();
x.Dump();
writer.Close();
reader.Close();
strm.Close();
Output
<string>test</string>
Comment out line 3 and the Output is
<?xml version="1.0" encoding="utf-8"?><string>test</string>
Just to simplify the soln. of the original problem of removing UTF encoding declaration
here is the code
StringBuilder sb = new StringBuilder();
var serializer = new System.Xml.Serialization.XmlSerializer(typeToSerialize.GetType());
serializer.Serialize(System.Xml.XmlWriter.Create(sb, new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent=true }), typeToSerialize);

Categories

Resources