2010-02-26 40 views
34

假設我有一個簡單的類,只有一個成員一個字符串。如何讓XmlSerializer在字符串中殺死NewLines?

public class Abc 
{ 
    private String text; 

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

現在,當我序列,然後與可疑XmlSerializer的反序列化任何含文本換行(「\ r \ n」或Environment.NewLine)被變換到「\ N」。

如何保留換行符?

+0

你序列化它在哪裏?什麼流或文字作家? – 2010-02-26 07:58:06

+0

我做了一個演示應用程序來顯示我的問題: http://c0065612.cdn.cloudfiles.rackspacecloud.com/XmlDeSerTextBox.zip – Thomas 2010-02-26 09:02:14

+0

該應用程序顯示兩個文本框和一個按鈕。當您在上方文本框中輸入帶有換行符的文本並按下「確定」時,XmlSerializer會爲您破壞換行符。 – Thomas 2010-02-26 09:09:52

回答

52

它不是XmlSerializer,而是移除您的CR的XmlWriter。爲了保留它,我們必須讓作者將CR轉換爲其字符實體

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

我們爲什麼要這麼做?

這是因爲符合的XML解析器在解析之前必須將CRLF和任何沒有跟隨LF的CR翻譯爲單個LF。此行爲在XML 1.0規範的End-of-Line handling部分中定義。

由於在解析之前發生這種情況,如果您希望CR存在於文檔中,則需要將CR編碼爲其字符實體。

+0

是的!這樣可行。謝謝。 – Thomas 2010-02-26 10:54:05

+2

我認爲回車是 而不是 – Juan 2011-01-06 17:57:47

+0

@Lachlan Roche我發現這個解決方案是XML解決文本字符串問題的唯一答案之一。我的問題是,它是通過Web服務發生的,自動生成的代碼用於構建wsdl。我想知道你是否對如何解決問題有所建議? – htm11h 2013-06-03 16:35:21

0

使用此代碼:

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(); 
} 
+0

今天你應該使用'XmlReader'而不是'XmlTextReader'。你也可以用前者來達到同樣的效果。不過,答案很好。 – nawfal 2014-07-15 21:36:36

+0

不錯,你能解釋一下你的代碼嗎? – 2015-09-03 12:44:47

+0

@nawfal:你能解釋如何用XmlReader做到這一點嗎? – 2015-09-03 12:56:32

2
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()); 
     } 
    } 

} 
1

公共類BinarySerialize其中T:新的() { 公共靜態字符串序列化(T選項,字符串路徑) {

  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; 

     } 
    }