2010-11-02 26 views
18

tengo el siguiente código:Al guardar un XmlDocument, no tiene en cuenta la codificación en el XmlDeclaration (UTF-8) y utiliza 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())); 

Y aquí está la salida:

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

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

Básicamente lo que does es crear un archivo xml y establecer la codificación en utf8, pero cuando lo guarda en stringwriter ignora mi codificación y usa utf16. Sin embargo, cuando se utiliza una secuencia de memoria, utiliza UTF-8 (con los caracteres adicionales BOM)

¿Por qué es esto? ¿Por qué no está honrando mi configuración de codificación explícita de utf-8?

Muchas gracias

+0

Sólo por curiosidad, ¿trató de dar nulo/cadena. vacío en la codificación y ver? – user281693

+0

Si hago eso, el stringwriter sigue siendo utf16, y el memorystream no tiene codificación en su declaración. – Chris

+0

por ej. se ve así: Chris

Respuesta

26

porque todo lo que está haciendo es el establecimiento de un elemento XML que dice que es UTF-8, que está en realidad no guardarlo como UTF-8. Es necesario establecer el flujo de salida a usar UTF-8, así:

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 vez hecho esto, usted ni siquiera tiene que agregar la declaración XML. Lo descubre por sí mismo. Si desea guardarlo en un MemoryStream, use un StreamWriter que envuelve el MemoryStream.

+1

Ok, eso tiene sentido ahora. Gracias – Chris

+0

Así que el escritor xml anula todo lo que pones en la declaración xml, dependiendo de en qué se está guardando, ya sea una secuencia o un escritor de texto o un archivo. – Chris

+0

La Declaración XML es simplemente un elemento (aunque extraño) en lo que a ella respecta. Declara cómo se guarda, no cómo se debe guardar. Es por eso que cuando se guarda, lo pone a su disposición. – vcsjones

2

De the MSDN podemos ver ...

La codificación en el TextWriter determina la codificación que se escribe a cabo (La codificación del nodo XmlDeclaration se sustituye por la codificación de el TextWriter). Si no se especificó ninguna codificación en TextWriter, XmlDocument se guarda sin un atributo de codificación.

Si desea utilizar la codificación de XmlDeclaration, deberá usar una secuencia para guardar el documento.

+0

¿Entonces básicamente está diciendo que C# ignora la declaración xml al guardar el documento en un escritor de texto? – Chris

2

utilizo el siguiente método, que lo escribe muy y como 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; 
} 

llamar así:

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