Domanda

Ho una funzione per creare alcuni XmlDocument:

public string CreateOutputXmlString(ICollection<Field> fields)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.Encoding = Encoding.GetEncoding("windows-1250");

    StringBuilder builder = new StringBuilder();
    XmlWriter writer = XmlWriter.Create(builder, settings);

    writer.WriteStartDocument();
    writer.WriteStartElement("data");
    foreach (Field field in fields)
    {
        writer.WriteStartElement("item");
        writer.WriteAttributeString("name", field.Id);
        writer.WriteAttributeString("value", field.Value);
        writer.WriteEndElement();
    }
    writer.WriteEndElement();
    writer.Flush();
    writer.Close();

    return builder.ToString();
}

Ho impostato una codifica ma dopo aver creato XmlWriter ha la codifica utf-16. So che è perché le stringhe (e StringBuilder suppongo) sono codificate in utf-16 e non puoi cambiarle.
Quindi, come posso creare facilmente questo XML con l'attributo di codifica impostato su " windows-1250 " ;? non deve nemmeno essere codificato in questa codifica, deve solo avere l'attributo specificato.

modifica: deve essere in .Net 2.0, quindi non è possibile utilizzare alcun nuovo elemento del framework.

È stato utile?

Soluzione

Devi usare StringWriter con la codifica appropriata. Purtroppo StringWriter non ti consente di specificare direttamente la codifica, quindi hai bisogno di una classe come questa:

public sealed class StringWriterWithEncoding : StringWriter
{
    private readonly Encoding encoding;

    public StringWriterWithEncoding (Encoding encoding)
    {
        this.encoding = encoding;
    }

    public override Encoding Encoding
    {
        get { return encoding; }
    }
}

( Questa domanda è simile ma non del tutto duplicata .)

EDIT: per rispondere al commento: passa StringWriterWithEncoding a XmlWriter.Create anziché StringBuilder, quindi chiama ToString () su di esso alla fine.

Altri suggerimenti

Solo alcune spiegazioni extra sul perché sia ??così.

Le stringhe sono sequenze di caratteri, non byte. Le stringhe, di per sé, non sono "codificate", poiché utilizzano caratteri che sono memorizzati come punti di codice Unicode. La codifica NON RENDE SENSO a livello di stringa.

Una codifica è una mappatura da una sequenza di punti di codice (caratteri) a una sequenza di byte (per l'archiviazione su sistemi basati su byte come filesystem o memoria). Il framework non consente di specificare le codifiche, a meno che non vi sia una ragione convincente per, come adattare i punti di codice a 16 bit sulla memoria basata su byte.

Quindi quando provi a scrivere il tuo XML in StringBuilder, stai effettivamente costruendo una sequenza XML di caratteri e scrivendoli come sequenza di caratteri, quindi non viene eseguita alcuna codifica. Pertanto, nessun campo di codifica.

Se si desidera utilizzare una codifica, XmlWriter deve scrivere su uno stream.

Informazioni sulla soluzione che hai trovato con MemoryStream, senza offesa, ma si tratta solo di sbattere le braccia e muovere aria calda. Stai codificando i tuoi punti di codice con 'windows-1252', e quindi analizzandoli di nuovo in punti di codice. L'unica modifica che può verificarsi è che i caratteri non definiti in windows-1252 vengano convertiti in un '?' personaggio nel processo.

Per me, la soluzione giusta potrebbe essere la seguente. A seconda della funzione utilizzata, è possibile passare uno Stream come parametro alla propria funzione, in modo che il chiamante decida se deve essere scritto in memoria o in un file. Quindi sarebbe scritto in questo modo:


        public static void WriteFieldsAsXmlDocument(ICollection fields, Stream outStream)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.Encoding = Encoding.GetEncoding("windows-1250");

            using(XmlWriter writer = XmlWriter.Create(outStream, settings)) {
                writer.WriteStartDocument();
                writer.WriteStartElement("data");
                foreach (Field field in fields)
                {
                    writer.WriteStartElement("item");
                    writer.WriteAttributeString("name", field.Id);
                    writer.WriteAttributeString("value", field.Value);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
        }
MemoryStream memoryStream = new MemoryStream();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = Encoding.UTF8;

XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("root", "http://www.timvw.be/ns");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();

string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray());

Da qui

In realtà ho risolto il problema con MemoryStream:

public static string CreateOutputXmlString(ICollection<Field> fields)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.Encoding = Encoding.GetEncoding("windows-1250");

            MemoryStream memStream = new MemoryStream();
            XmlWriter writer = XmlWriter.Create(memStream, settings);

            writer.WriteStartDocument();
            writer.WriteStartElement("data");
            foreach (Field field in fields)
            {
                writer.WriteStartElement("item");
                writer.WriteAttributeString("name", field.Id);
                writer.WriteAttributeString("value", field.Value);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.Flush();
            writer.Close();

            writer.Flush();
            writer.Close();

            string xml = Encoding.GetEncoding("windows-1250").GetString(memStream.ToArray());

            memStream.Close();
            memStream.Dispose();

            return xml;
        }

Ho risolto il mio inviando la stringa a una variabile e sostituendo qualsiasi riferimento a utf-16 con utf-8 (la mia app aveva bisogno della codifica UTF8). Dal momento che stai usando una funzione, potresti fare qualcosa di simile. Uso principalmente VB.net, ma penso che il C # sarebbe simile a questo.

return builder.ToString().Replace("utf-16", "utf-8");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top