2010-11-02 12 views
18

Mam następujący kod:Podczas zapisywania XmlDocument, ignoruje kodowanie w XmlDeclaration (UTF-8) i wykorzystuje 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())); 

I tu jest wyjście:

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

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

Zasadniczo co go robi plik xml i ustawia kodowanie na utf8, ale kiedy zapisuje go do stringwriter, ignoruje moje kodowanie i używa utf16. Jednak podczas korzystania ze strumienia pamięci używa on utf8 (z dodatkowymi znakami BOM).

Dlaczego tak jest? Dlaczego nie honoruje mojego jawnego ustawienia kodowania dla utf-8?

Thanks a lot

+0

tylko ciekaw, czy spróbować dając zerowy/string. pusty w kodowaniu i patrz? – user281693

+0

Jeśli to zrobię, stringwriter nadal będzie utf16, a komunikat memorystrujący nie będzie zawierał kodowania w deklaracji. – Chris

+0

np. Wygląda to tak: Chris

Odpowiedz

26

Ponieważ wszystko, co robisz, to ustawienie elementu XML, który mówi, że jest to UTF-8, w rzeczywistości nie zapisujesz go jako UTF-8. Trzeba ustawić strumień wyjściowy używać UTF-8, tak:

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

Gdy to zrobisz, nie trzeba nawet dodawać deklarację XML. Wykreśla to na własną rękę. Jeśli chcesz zapisać go w obiekcie MemoryStream, użyj StreamWriter, który otoczy obiekt MemoryStream.

+1

OK, teraz ma to sens. Dzięki – Chris

+0

Pisarz xml przesłania wszystko, co umieścisz w deklaracji xml, w zależności od tego, do czego jest zapisywane, czy to strumień, tekst lub plik tekstowy. – Chris

+0

Deklaracja XML jest po prostu elementem (aczkolwiek dziwnym), jeśli o nią chodzi. Deklaruje, w jaki sposób jest zapisywany, a nie w jaki sposób należy go zapisać. Dlatego, gdy jest zapisany, umieszcza go tam dla ciebie. – vcsjones

2

Od the MSDN widzimy ...

Kodowanie na kodowanie TextWriter określa, co jest napisane na zewnątrz (Kodowanie węzła XmlDeclaration otrzymuje kodowania TextWriter). Jeśli nie określono kodowania w TextWriter, XmlDocument jest zapisany bez atrybutu kodowania.

Jeśli chcesz użyć kodowania z XmlDeclaration, musisz użyć strumienia do zapisania dokumentu.

+0

Więc w zasadzie mówisz, że C# ignoruje xmldeclaration podczas zapisywania dokumentu do autora tekstów? – Chris

2

używam następującą metodę, zapisuje go całkiem i jako 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; 
} 

nazywają go lubię:

File.WriteAllText(fileName, Utilities.Beautify(xmlDocument)); 
Powiązane problemy