XmlWriter per scrivere su una stringa anziché su un file


118

Ho un servizio WCF che deve restituire una stringa di XML. Ma sembra che lo scrittore voglia solo creare un file, non una stringa. Provai:

string nextXMLstring = "";
using (XmlWriter writer = XmlWriter.Create(nextXMLstring))

Questo genera un errore che dice che nextXMLstring non ha un percorso di file. Vuole qualcosa come:

using (XmlWriter writer = XmlWriter.Create("nextXMLstring.xml"))

Come posso creare il mio XML e poi restituirlo come una stringa?

Grazie!!

Risposte:


217

È necessario creare un StringWriter e passarlo a XmlWriter.

L'overload della stringa di XmlWriter.Create è per un nome file.

Per esempio

using (var sw = new StringWriter()) {
  using (var xw = XmlWriter.Create(sw)) {
    // Build Xml with xw.


  }
  return sw.ToString();
}

2
@ Will: ha annullato la modifica. XmlTextWriter.Close () verrà scaricato nel flusso, quindi è necessario che ciò accada prima di estrarre la stringa. (Poca differenza in questo caso, ma preferisco farlo in modo coerente perché la semantica flush delle classi * Writer e Stream non è sempre chiaramente documentata.)
Richard

1
Solo un commento per le persone che lo usano. Se ti capita di omettere using () e invece dichiari normalmente il tuo XmlWriter, assicurati di chiamare xw.Flush prima di chiamare sw.ToString () altrimenti potresti non ottenere tutto il contenuto! (Ovviamente meglio usare le parentesi graffe ...)
Ravendarksky

Tieni presente che il codice seguente fornisce un avviso CA2202 durante l'analisi del codice, perché il metodo Dispose () verrà chiamato due volte sull'oggetto StringWriter
Łukasz Kosiak

113

Come ha detto Richard, StringWriterè la via da seguire. C'è un intoppo, tuttavia: per impostazione predefinita, StringWritersi pubblicizzerà come in UTF-16. Di solito XML è in UTF-8. Puoi risolvere questo problema creando una sottoclasse StringWriter;

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

Ciò influenzerà la dichiarazione scritta da XmlWriter. Ovviamente, se poi scrivi la stringa altrove in forma binaria, assicurati di utilizzare una codifica che corrisponda a quella che hai corretto per il file StringWriter. (Il codice precedente presuppone sempre UTF-8; è banale creare una versione più generale che accetti una codifica nel costruttore.)

Dovresti quindi utilizzare:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}

Jon, sei sicuro che writernon venga eliminato più di una volta?
rasx

2
@rasx: Potrebbe essere, ma non importa.
Jon Skeet

30

So che è vecchio e ha risposto, ma ecco un altro modo per farlo. Soprattutto se non vuoi la distinta componenti UTF8 all'inizio della tua stringa e vuoi che il testo sia rientrato:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}

3
Encoding.UTF8.GetString(ms.ToArray())è la semplificazione al tuo ritorno.
SliverNinja - MSFT

1
ms.ToArray()non restituisce alcun articolo quando l'ho provato. Ho dovuto aggiungere x.Close()o spostare l'istruzione return appena fuori dall'istruzione using interna.
Rich C

Esegue utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); lavoro?
Brianary

1
@ Rich C - Ho il sospetto che sia perché il tuo flusso non è stato scaricato. XmlTextWriter sarebbe stato eliminato al di fuori della sua istruzione using, il che ne avrebbe causato lo svuotamento.
yourbuddypal

14

Usa StringBuilder:

var sb = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(sb))
    {
        ...
    }
return sb.ToString();

1

Ragazzi, non dimenticate di chiamare xmlWriter.Close () e xmlWriter.Dispose () altrimenti la vostra stringa non finirà di essere creata. Sarà solo una stringa vuota


Non preoccuparti, l'utilizzo dell'istruzione gestirà l'eliminazione dell'oggetto.

Questa è una domanda del 2009. Quindi, il valore nel fornire una risposta ora sarebbe per i futuri utenti che potrebbero avere problemi simili. Di conseguenza, le risposte a vecchie domande come questa dovrebbero essere fornite solo se possono identificare chiaramente il problema e spiegare / fornire una soluzione. Di solito è inutile cercare di coinvolgere l'OP in una conversazione poiché è probabile che sia andato avanti.
MikeC

Stavo esaminando tutti questi esempi e mi chiedevo perché ottengo una stringa vuota. xmlWriter.Close()era la soluzione.
Rafał Ryszkowski

-1

Beh, penso che la soluzione più semplice e veloce qui sarebbe solo quella di:

StringBuilder sb = new StringBuilder();

using (var writer = XmlWriter.Create(sb, settings))
{
    ... // Whatever code you have/need :)

    sb = sb.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); //Or whatever uft you want/use.
    //Before you finally save it:
    File.WriteAllText("path\\dataName.xml", sb.ToString());
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.