2010-11-02 53 views
18

我有以下代碼:當保存一個XmlDocument,它忽略了編碼的XmlDeclaration(UTF8),並使用UTF16

var doc = new XmlDocument(); 

XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null); 
doc.AppendChild(xmlDeclaration); 

XmlElement root = doc.CreateElement("myRoot"); 
doc.AppendChild(root); 
root.InnerText = "myInnerText"; 

StringWriter sw = new StringWriter(); 
doc.Save(sw); 
Console.WriteLine(sw.ToString()); 

Console.WriteLine(); 

MemoryStream ms = new MemoryStream(); 
doc.Save(ms); 
Console.WriteLine(Encoding.ASCII.GetString(ms.ToArray())); 

這裏是輸出:

<?xml version="1.0" encoding="utf-16"?> 
<myRoot>myInnerText</myRoot> 

???<?xml version="1.0" encoding="UTF-8"?> 
<myRoot>myInnerText</myRoot> 

基本上它確實是製作一個xml文件,並將編碼設置爲utf8,但是當它將其保存到字符串編寫器時,它會忽略我的編碼並使用utf16。但是,當使用內存流時,它使用utf8(帶有額外的BOM字符)

這是爲什麼?爲什麼它不遵守我的顯式編碼設置utf-8?

非常感謝

+0

只是好奇,你有沒有試着給空/串。在編碼中清空並看到? – user281693 2010-11-02 03:11:02

+0

如果我這樣做,那麼stringwriter仍然是utf16,並且內存流在其聲明中沒有編碼。 – Chris 2010-11-02 03:20:29

+0

例如。它看起來像這樣:<?xml version =「1.0」?> – Chris 2010-11-02 03:20:48

回答

26

因爲你所做的只是設置一個XML元素來表示它是UTF-8,你實際上並沒有將它保存爲UTF-8。您需要設置輸出流使用UTF-8,這樣的:

var doc = new XmlDocument(); 
XmlElement root = doc.CreateElement("myRoot"); 
doc.AppendChild(root); 
root.InnerText = "myInnerText"; 
using(TextWriter sw = new StreamWriter("C:\\output.txt", false, Encoding.UTF8)) //Set encoding 
{ 
    doc.Save(sw); 
} 

一旦你這樣做,你甚至不用添加XML聲明。它自行計算出來。如果您想將其保存到MemoryStream中,請使用包裝MemoryStream的StreamWriter。

+1

好吧,現在有道理。謝謝 – Chris 2010-11-02 03:28:19

+0

因此,xml編寫器會覆蓋您放入xml聲明的任何內容,具體取決於它保存的內容,可以是流或者textwriter或文件。 – Chris 2010-11-02 03:29:10

+0

就其而言,XML聲明只是一個元素(儘管是一個奇怪的元素)。它聲明瞭它如何被保存,而不是如何保存。這就是爲什麼當它被保存時,它會將它放在你的身邊。 – vcsjones 2010-11-02 03:36:57

2

the MSDN我們可以看到... ...

上的TextWriter的編碼確定寫出編碼(該XmlDeclaration節點的編碼是由編碼代替TextWriter)。如果在TextWriter上沒有指定編碼,則保存XmlDocument而沒有編碼屬性。

如果您想使用XmlDeclaration中的編碼,您需要使用流來保存文檔。

+0

所以基本上你說C#在將文檔保存到一個textwriter時忽略xmldeclaration? – Chris 2010-11-02 03:27:53

2

我用下面的方法,它把它寫到漂亮爲UTF-8

public static string Beautify(XmlDocument doc) 
{ 
    string xmlString = null; 
    using (MemoryStream ms = new MemoryStream()) { 
     XmlWriterSettings settings = new XmlWriterSettings { 
      Encoding = new UTF8Encoding(false), 
      Indent = true, 
      IndentChars = " ", 
      NewLineChars = "\r\n", 
      NewLineHandling = NewLineHandling.Replace 
     }; 
     using (XmlWriter writer = XmlWriter.Create(ms, settings)) { 
      doc.Save(writer); 
     } 
     xmlString = Encoding.UTF8.GetString(ms.ToArray()); 
    } 
    return xmlString; 
} 

這樣稱呼它:

File.WriteAllText(fileName, Utilities.Beautify(xmlDocument));