2010-10-06 18 views
32

Je veux être en mesure d'écrire du XML dans une chaîne avec la déclaration et avec un codage UTF-8. Cela semble vraiment difficile à accomplir.Force XDocument à écrire en chaîne avec l'encodage UTF-8

J'ai lu un peu et essayé quelques-unes des réponses populaires pour cela, mais ils ont tous des problèmes. Mon code actuel est correctement sorti en UTF-8 mais ne conserve pas le formatage original du document XDocument (c'est-à-dire indents/whitespace)!

Quelqu'un peut-il vous donner des conseils s'il vous plaît?

XDocument xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), xelementXML); 

MemoryStream ms = new MemoryStream(); 
using (XmlWriter xw = new XmlTextWriter(ms, Encoding.UTF8)) 
{ 
    xml.Save(xw); 
    xw.Flush(); 

    StreamReader sr = new StreamReader(ms); 
    ms.Seek(0, SeekOrigin.Begin); 

    String xmlString = sr.ReadToEnd(); 
} 

Le XML nécessite la mise en forme identique à la façon .ToString() formaterait il-à-dire

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<root> 
    <node>blah</node> 
</root> 

Ce que je suis en train de voir est

<?xml version="1.0" encoding="utf-8" standalone="yes"?><root><node>blah</node></root> 

Mise à jour Je réussi à obtenir ce travail en ajoutant XmlTextWriter paramètres ... Il semble très maladroit si !

MemoryStream ms = new MemoryStream(); 
XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Encoding = Encoding.UTF8; 
settings.ConformanceLevel = ConformanceLevel.Document; 
settings.Indent = true; 
using (XmlWriter xw = XmlTextWriter.Create(ms, settings)) 
{ 
    xml.Save(xw); 
    xw.Flush(); 

    StreamReader sr = new StreamReader(ms); 
    ms.Seek(0, SeekOrigin.Begin); 
    String blah = sr.ReadToEnd(); 
} 
+0

Qu'est-ce que 'formatage'? Vous n'avez rien dit sur le formatage! – AakashM

+0

L'espace/formatage habituel que vous obtenez si vous juste à '.ToString()' sur un 'XDocument' ou' XElement' – Chris

+0

S'il vous plaît donner un exemple de document d'entrée afin que nous puissions tester les réponses. –

Répondre

53

Essayez ceci:

using System; 
using System.IO; 
using System.Text; 
using System.Xml.Linq; 

class Test 
{ 
    static void Main() 
    { 
     XDocument doc = XDocument.Load("test.xml", 
             LoadOptions.PreserveWhitespace); 
     doc.Declaration = new XDeclaration("1.0", "utf-8", null); 
     StringWriter writer = new Utf8StringWriter(); 
     doc.Save(writer, SaveOptions.None); 
     Console.WriteLine(writer); 
    } 

    private class Utf8StringWriter : StringWriter 
    { 
     public override Encoding Encoding { get { return Encoding.UTF8; } } 
    } 
} 

Bien sûr, vous nous avez pas montré comment vous construisez le document, ce qui le rend difficile à tester ... Je viens d'essayer avec un Construit à la main XDocument et qui contient également les espaces blancs.

+0

Fonctionne un régal, merci - est-il impossible de trier l'encodage sans hériter de StringWriter? – Chris

+0

@Chris: Il est * possible * qu'il y ait un moyen d'obtenir la surcharge de TextWriter pour ignorer l'encodage que le TextWriter annonce, mais j'ai trouvé que c'était un hack très simple pour faire le travail. (Vous en avez seulement besoin en un seul endroit ...) –

+0

Ouais je l'aime - c'est beaucoup mieux que la méthode que je suis venu avec. Merci – Chris

2

Try XmlWriterSettings:

XmlWriterSettings xws = new XmlWriterSettings(); 
xws.OmitXmlDeclaration = false; 
xws.Indent = true; 

et la transmettre comme

using (XmlWriter xw = XmlWriter.Create(sb, xws))