如何保持XmlSerializer杀死string中的NewLines?

假设我有一个简单的类,只有一个成员一个string。

public class Abc { private String text; public String Text { get { return this.text; } set { this.text = value; } } } 

现在,当我序列化,然后使用可疑的XmlSerializer反序列化它时,任何包含换行符('\ r \ n'或Environment.NewLine)的文本都会被转换为'\ n'。

我如何保留换行符?

它不是XmlSerializer,而是删除您的CR的XmlWriter。 为了保留它,我们必须让作者将CR转换为它的angular色实体

 XmlWriterSettings ws = new XmlWriterSettings(); ws.NewLineHandling = NewLineHandling.Entitize; XmlSerializer ser = new XmlSerializer( typeof( Abc ) ); using (XmlWriter wr = XmlWriter.Create( "abc.xml", ws )) { ser.Serialize( wr, s ); } 

这与DataContractSerializer完全相同:

 var ser = new DataContractSerializer( typeof( Abc ) ); using (XmlWriter wr = XmlWriter.Create( "abc.xml", ws )) { ser.Serialize( wr, s ); } 

为什么我们需要这样做?

这是因为符合的XMLparsing器在parsing之前必须将CRLF和任何没有跟随LF的CR转换为单个LF。 此行为在XML 1.0规范的行尾处理部分中定义。

在parsing之前发生这种情况,如果要在文档中存在CR,则需要将CR编码为其字符实体。

 public class SerializeAny<TF> where TF : new() { public static TF Deserialize(string serializedData) { try { var xmlSerializer = new XmlSerializer(typeof(TF)); TF collection; using (var xmlReader = new XmlTextReader(serializedData, XmlNodeType.Document, null)) { collection = (TF)xmlSerializer.Deserialize(xmlReader); } return collection; } catch (Exception) { } return new TF(); } public static TF DeserializeZip(string path) { try { var bytes = File.ReadAllBytes(path); string serializedData = Unzip(bytes); TF collection = Deserialize(serializedData); return collection; } catch (Exception) { } return new TF(); } public static string Serialize(TF options) { var xml = ""; try { var xmlSerializer = new XmlSerializer(typeof(TF)); using (var stringWriter = new StringWriter()) { xmlSerializer.Serialize(stringWriter, options); xml = stringWriter.ToString(); } } catch (Exception ex) { return ex.Message; } return xml; } public static string SerializeZip(TF options, string path) { var xml = ""; try { xml = Serialize(options); var zip = Zip(xml); File.WriteAllBytes(path, zip); } catch (Exception ex) { return ex.Message; } return xml; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] internal static String SerializeObject<T>(T obj, Encoding enc) { using (var ms = new MemoryStream()) { var xmlWriterSettings = new System.Xml.XmlWriterSettings() { // If set to true XmlWriter would close MemoryStream automatically and using would then do double dispose // Code analysis does not understand that. That's why there is a suppress message. CloseOutput = false, Encoding = enc, OmitXmlDeclaration = false, Indent = true }; using (var xw = XmlWriter.Create(ms, xmlWriterSettings)) { var s = new XmlSerializer(typeof(T)); s.Serialize(xw, obj); } return enc.GetString(ms.ToArray()); } } private static void CopyTo(Stream src, Stream dest) { byte[] bytes = new byte[4096]; int cnt; while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) { dest.Write(bytes, 0, cnt); } } private static byte[] Zip(string str) { var bytes = Encoding.UTF8.GetBytes(str); using (var msi = new MemoryStream(bytes)) using (var mso = new MemoryStream()) { using (var gs = new GZipStream(mso, CompressionMode.Compress)) { //msi.CopyTo(gs); CopyTo(msi, gs); } return mso.ToArray(); } } private static string Unzip(byte[] bytes) { using (var msi = new MemoryStream(bytes)) using (var mso = new MemoryStream()) { using (var gs = new GZipStream(msi, CompressionMode.Decompress)) { CopyTo(gs, mso); } return Encoding.UTF8.GetString(mso.ToArray()); } } } 

公共类BinarySerialize其中T:新(){公共静态string序列化(T选项,stringpath){

  var xml = ""; try { File.Delete(path); } catch (Exception) { } try { using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { var bf = new BinaryFormatter(); bf.Serialize(fs, options); } } catch (Exception ex) { return ex.Message; } return xml; } public static T Deserialize(string path) { T filteroptions; using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { var bf = new BinaryFormatter(); filteroptions = (T)bf.Deserialize(fs); } return filteroptions; } } 

使用此代码:

 public static FilterOptions Deserialize(string serializedData) { try { var xmlSerializer = new XmlSerializer(typeof(FilterOptions)); var xmlReader = new XmlTextReader(serializedData,XmlNodeType.Document,null); var collection = (FilterOptions)xmlSerializer.Deserialize(xmlReader); return collection; } catch (Exception) { } return new FilterOptions(); }