2010-11-02 12 views
18

Ho il codice seguente:Quando si salva un XmlDocument, ignora la codifica nel XmlDeclaration (UTF8) e utilizza 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())); 

Ed ecco l'output:

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

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

Fondamentalmente ciò che fa un file xml e imposta la codifica su utf8, ma quando lo salva su stringwriter ignora la mia codifica e usa utf16. Tuttavia, quando si utilizza un flusso di memoria, utilizza utf8 (con i caratteri BOM extra)

Perché è questo? Perché non sta onorando la mia impostazione di codifica esplicita di utf-8?

Grazie mille

+0

Solo per curiosità, ha fatto si tenta dando nullo/string. vuoto nella codifica e vedi ?? – user281693

+0

Se lo faccio, lo stringwriter è ancora utf16 e il memorystream non ha codifica nella sua dichiarazione. – Chris

+0

es. assomiglia a questo: Chris

risposta

26

Poiché tutto ciò che si sta facendo è impostare un elemento XML che dice che è UTF-8, in realtà non lo si sta salvando come UTF-8. È necessario impostare il flusso di output per utilizzare UTF-8, in questo modo:

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

Una volta fatto questo, non hanno nemmeno bisogno di aggiungere la dichiarazione XML. Lo capisce da solo. Se si desidera salvarlo su un MemoryStream, utilizzare uno StreamWriter che avvolge MemoryStream.

+1

Ok questo ha senso ora. Grazie – Chris

+0

Quindi lo scrittore xml sovrascrive qualsiasi cosa tu abbia inserito nella dichiarazione xml, a seconda di cosa sta salvando, che sia un flusso o un testo o un file. – Chris

+0

La dichiarazione XML è semplicemente un elemento (anche se strano) per quanto lo riguarda. Dichiara come viene salvato, non come dovrebbe essere salvato. Ecco perché quando viene salvato lo mette lì per te. – vcsjones

2

Da the MSDN possiamo vedere ...

La codifica sulla TextWriter determina la codifica che viene trascritta (La codifica del nodo XmlDeclaration è sostituita dalla codifica di il TextWriter). Se non è stata specificata alcuna codifica in TextWriter, XmlDocument viene salvato senza un attributo di codifica.

Se si desidera utilizzare la codifica da XmlDeclaration, è necessario utilizzare un flusso per salvare il documento.

+0

Quindi in pratica stai dicendo che C# ignora la xmldeclaration quando salva il documento in un textwriter? – Chris

2

Io uso il seguente metodo, si scrive fuori abbastanza e come 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; 
} 

chiamare in:

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