I am writing an xml file but am missing some value for specific field. I check that when the object comes which contains the value that specific value exist, but after writing the xml the value doesn't exist.
This is the code that I use, I think XmlTextWriter could be the cause of the wrong xml.
There is another method which could be used for it, that is TextWriter but it failed to convert into memorystream.
string xmlString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(T));
// XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.ASCII);
TextWriter xmlTextWriter=new StreamWriter(memoryStream,Encoding.ASCII);
xs.Serialize(xmlTextWriter, obj);
memoryStream =(MemoryStream)xmlTextWriter.
//(MemoryStream)xmlTextWriter.BaseStream;
xmlString = ASCIIByteArrayToString(memoryStream.ToArray());
return `xmlString;`
Any idea how I can know why and where the problem occurs.
I think you are over-complicating it with the memory stream. You can serialize to a StringWriter (which derives from TextWriter) then call ToString() if you want to get the XML string.
XmlSerializer xs = new XmlSerializer(typeof(T));
StringWriter sw = new StringWriter();
xs.Serialize(sw, obj);
return sw.ToString();
Try disposing properly your IDisposable resources by wrapping them in using statements:
public string SerializeToXml<T>(T obj)
{
using (var stream = new MemoryStream())
{
var xs = new XmlSerializer(typeof(T));
xs.Serialize(stream, obj);
return Encoding.UTF8.GetString(stream.ToArray());
}
}
Related
I am trying to serialize an object to XML and the problem that I am getting is that the object gets serialized to
<something />
instead of
<something/>
I believe that both are valid XML syntax, but I have to get <something/>
Here is my code
public static string Serialize<T>(T ObjectToSerialize)
{
XmlWriterSettings settings = new XmlWriterSettings()
{
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8,
};
XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
using (var xw = XmlWriter.Create(textWriter, settings))
{
xmlSerializer.Serialize(xw, ObjectToSerialize);
}
return textWriter.ToString();
}
}
How can I fix it?
May not be the most efficient solution, but you could do a simple String.Replace before returning serialized data in Serialize<T>().
Replacing
return textWriter.ToString();
With
return textWriter.ToString().Replace(" />","/>");
I have an XML file on a given location and I want to have the content of the XML in a string variable. However, when I print it out, the encoding changes. This is how I am doing it.
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(xmlFileLocation);
using (StringWriter stringWriter = new StringWriter(new StringBuilder()))
{
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter) { Formatting = Formatting.Indented })
{
xmlFile.Save(xmlTextWriter);
}
return stringWriter.ToString();
}
When I try to initialize the XmlTextWriter (new XmlTextWriter(stringWriter, Encoding.UTF8)) with a given encoding, then I have issues with the StringWriter but I don't know how to sort it out. Any idea?
The issue is: Cannot convert from StringWriter into Stream
Encoding using StringWriter always will be UTF-16 and cannot be changed. When you want to use a StringWriter with different encoding it is possible to subclass StringWriter. Please refer to this answer on how to do so.
Using your code this would then change to
using (EncodingStringWriter eStringWriter = new EncodingStringWriter (new StringBuilder(), Encoding.UTF8))
{
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter) { Formatting = Formatting.Indented })
{
xmlFile.Save(xmlTextWriter);
}
return eStringWriter.ToString();
}
Recently upgraded a 3.5 project to 4.5. There is a chunk of data that we are serializing and storing in the database, but everytime a save occurs in the upgraded project, the XML formatting has changed, throwing errors, and I can't seem to figure out the core issue. There are 2 SO questions in particular that mention encoding changes, but I've tried switching to UTF8 (in a few different ways specified in the answers on those questions), without any success - with UTF8 I just got a mess of strange characters throughout the entire file.
The main issues that I can see occurring are:
A leading ? character is added to the XML (which I've come to find out is a valid character, but we aren't handling apparently)
Child nodes aren't being included with some of the nodes.
Here is our serialization method:
public static string SerializeXml<T>(T instance)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
MemoryStream memStream = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(memStream, Encoding.Unicode);
serializer.Serialize(xmlWriter, instance);
memStream = (MemoryStream)xmlWriter.BaseStream;
return UnicodeEncoding.Unicode.GetString(memStream.ToArray()).Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
}
and our deserialization method:
public static T DeserializeXml<T>(string xml)
{
XmlSerializer xs = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(xml);
return (T)xs.Deserialize(reader);
}
Any help would be appreciated, I am not too familiar with serialization or encoding. Just curious what may have changed with the upgrade to 4.5, or if there is something I need to take a closer look at.
If you want to Serialize to a String you need to use UTF16. If you want to Serialize with UTF8 you need to serialize to a byte[]. Strings in C# are UTF16 so in the code you posted I believe all your data is encoded with UTF16 but because you are omitting the Xml Declaration code assumes it is UTF8.
I would recommend using functions like this and not omitting the XmlDeclaration:
public static string SerializeXmlToString<T>(T instance)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.Unicode;
StringBuilder builder = new StringBuilder();
using (StringWriter writer = new StringWriter(builder))
using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
{
serializer.Serialize(xmlWriter, instance);
}
return builder.ToString();
}
public static byte[] SerializeXml<T>(T instance)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
using (MemoryStream memStream = new MemoryStream())
{
using (XmlWriter xmlWriter = XmlWriter.Create(memStream, settings))
{
serializer.Serialize(xmlWriter, instance);
}
return memStream.ToArray();
}
}
public static T DeserializeXml<T>(string data)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(data))
{
return (T)serializer.Deserialize(reader);
}
}
public static T DeserializeXml<T>(byte[] bytes)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using(MemoryStream stream = new MemoryStream(bytes))
{
return (T)serializer.Deserialize(stream);
}
}
I seem to be getting some junk at the head of my serialized XML string. I have a simple extension method
public static string ToXML(this object This)
{
DataContractSerializer ser = new DataContractSerializer(This.GetType());
var settings = new XmlWriterSettings { Indent = true };
using (MemoryStream ms = new MemoryStream())
using (var w = XmlWriter.Create(ms, settings))
{
ser.WriteObject(w, This);
w.Flush();
return UTF8Encoding.Default.GetString(ms.ToArray());
}
}
and when I apply it to my object I get the string
<?xml version="1.0" encoding="utf-8"?>
<RootModelType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WeinCad.Data">
<MoineauPump xmlns:d2p1="http://schemas.datacontract.org/2004/07/Weingartner.Numerics">
<d2p1:Rotor>
<d2p1:Equidistance>0.0025</d2p1:Equidistance>
<d2p1:Lobes>2</d2p1:Lobes>
<d2p1:MajorRadius>0.04</d2p1:MajorRadius>
<d2p1:MinorRadius>0.03</d2p1:MinorRadius>
</d2p1:Rotor>
</MoineauPump>
</RootModelType>
Note the junk at the beginning. When I try to deserialize this
I get an error. If I copy paste the XML into my source minus
the junk prefix I can deserialize it. What is the junk text
and how can I remove it or handle it?
Note my deserialization code is
public static RootModelType Load(Stream data)
{
DataContractSerializer ser = new DataContractSerializer(typeof(RootModelType));
return (RootModelType)ser.ReadObject(data);
}
public static RootModelType Load(string data)
{
using(var stream = new MemoryStream(Encoding.UTF8.GetBytes(data))){
return Load(stream);
}
}
This fix seems to work
public static string ToXML(this object obj)
{
var settings = new XmlWriterSettings { Indent = true };
using (MemoryStream memoryStream = new MemoryStream())
using (StreamReader reader = new StreamReader(memoryStream))
using(XmlWriter writer = XmlWriter.Create(memoryStream, settings))
{
DataContractSerializer serializer =
new DataContractSerializer(obj.GetType());
serializer.WriteObject(writer, obj);
writer.Flush();
memoryStream.Position = 0;
return reader.ReadToEnd();
}
}
I had a quick question regarding the datacontractserializer. Maybe it's more of a stream question. I found a piece of code that writes the xml to a filestream. I basically don't want the file and just need the string output.
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
var fs = new FileStream("test.xml", FileMode.OpenOrCreate);
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(fs, objectToSerialize);
fs.Close();
return fs.ToString();
}
fs.ToString() is obviously not what I'm looking for. What stream or writer etc, can I use just to return the proper string and not create a file? I did look at the XML the filestream created and it's exactly what I'm looking for. The XmlSerializer wrote the XML a bit strange and I prefer the output of the DataContractSerializer in this case. Can anyone point me in the right direction?
Something like this - put your output into a MemoryStream and then read that back in:
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
using(MemoryStream memStm = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(memStm, objectToSerialize);
memStm.Seek(0, SeekOrigin.Begin);
using(var streamReader = new StreamReader(memStm))
{
string result = streamReader.ReadToEnd();
return result;
}
}
}
Thanks to #xr280xr for pointing out my forgotten StringWriter disposal in the first draft.
/// <summary>
/// Converts this instance to XML.
/// </summary>
/// <returns>XML representing this instance.</returns>
public string ToXml()
{
var serializer = new DataContractSerializer(this.GetType());
using (var output = new StringWriter())
using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented })
{
serializer.WriteObject(writer, this);
return output.GetStringBuilder().ToString();
}
}
And even easier:
var serializer = new DataContractSerializer(typeof(T));
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
serializer.WriteObject(writer, objectToSerialize);
writer.Flush();
return sb.ToString();
}
I suggest combining the methods given by Pat and marc_s:
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
using (var output = new StringWriter())
using (var writer = new XmlTextWriter(output) {Formatting = Formatting.Indented})
{
new DataContractSerializer(typeof (T)).WriteObject(writer, objectToSerialize);
return output.GetStringBuilder().ToString();
}
}
A variant of #root's answer:
var serializer = new DataContractSerializer(typeof(T));
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
serializer.WriteObject(writer, objectToSerialize);
}
return sb.ToString();