XmlWriter zum Schreiben in einen String anstelle einer Datei

118

Ich habe einen WCF-Dienst, der eine XML-Zeichenfolge zurückgeben muss. Aber es scheint, als ob der Autor nur eine Datei erstellen möchte, keine Zeichenfolge. Ich habe es versucht:

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

Dies erzeugt einen Fehler, der besagt, dass nextXMLstring keinen Dateipfad hat. Es will so etwas wie:

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

Wie kann ich mein XML aufbauen und es dann als Zeichenfolge zurückgeben?

Vielen Dank!!

Blaze
quelle

Antworten:

217

Sie müssen einen StringWriter erstellen und diesen an den XmlWriter übergeben.

Die Zeichenfolgenüberladung von XmlWriter.Create bezieht sich auf einen Dateinamen.

Z.B

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


  }
  return sw.ToString();
}
Richard
quelle
2
@ Will: Rollte dein Wechselgeld zurück. XmlTextWriter.Close () wird in den Stream gespült. Dies soll vor dem Extrahieren der Zeichenfolge geschehen. (Kleiner Unterschied in diesem Fall, aber lieber konsequent, da die Flush-Semantik von * Writer- und Stream-Klassen nicht immer klar dokumentiert ist.)
Richard
1
Nur ein Kommentar für Leute, die dies benutzen. Wenn Sie das using () weglassen und stattdessen Ihren XmlWriter normal deklarieren, rufen Sie unbedingt xw.Flush auf, bevor Sie sw.ToString () aufrufen. Andernfalls erhalten Sie möglicherweise nicht den gesamten Inhalt! (Offensichtlich besser, die Klammern zu verwenden ...)
Ravendarksky
Beachten Sie, dass der folgende Code während der Codeanalyse eine CA2202-Warnung ausgibt. Die Methode Dispose () wird zweimal für das StringWriter-Objekt aufgerufen
Łukasz Kosiak,
113

Wie Richard sagte, StringWriterist der Weg nach vorne. Es gibt jedoch einen Haken: Standardmäßig StringWriterwird für UTF-16 geworben. Normalerweise ist XML in UTF-8. Sie können dies beheben, indem Sie StringWriter in Unterklassen unterteilen.

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

Dies wirkt sich auf die Erklärung von aus XmlWriter. Wenn Sie die Zeichenfolge dann an anderer Stelle in binärer Form ausschreiben, stellen Sie sicher, dass Sie eine Codierung verwenden, die mit der Codierung übereinstimmt, die Sie für die festgelegt haben StringWriter. (Der obige Code setzt immer UTF-8 voraus. Es ist trivial, eine allgemeinere Version zu erstellen, die eine Codierung im Konstruktor akzeptiert.)

Sie würden dann verwenden:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}
Jon Skeet
quelle
Jon, bist du sicher, dass writerdas nicht mehr als einmal entsorgt wird?
Rasx
2
@rasx: Es könnte sein - aber das spielt keine Rolle.
Jon Skeet
30

Ich weiß, dass dies alt und beantwortet ist, aber hier ist eine andere Möglichkeit, dies zu tun. Insbesondere, wenn Sie die UTF8-Stückliste nicht am Anfang Ihrer Zeichenfolge und den eingerückten Text möchten:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}
brianary
quelle
3
Encoding.UTF8.GetString(ms.ToArray())ist Vereinfachung bei Ihrer Rückkehr.
SliverNinja - MSFT
1
ms.ToArray()Gibt keine Artikel zurück, als ich dies versucht habe. Musste x.Close()die return-Anweisung direkt außerhalb der inneren using-Anweisung hinzufügen oder verschieben.
Rich C
Tut utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); Arbeit?
Brian
1
@ Rich C - Ich vermute, das liegt daran, dass Ihr Stream nicht geleert wurde. Der XmlTextWriter wäre außerhalb seiner using-Anweisung angeordnet worden, wodurch er geleert würde.
Yourbuddypal
13

Verwendung StringBuilder:

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

Jungs vergessen nicht, xmlWriter.Close () und xmlWriter.Dispose () aufzurufen, sonst wird Ihre Zeichenfolge nicht fertig erstellt. Es wird nur eine leere Zeichenfolge sein

saunupe1911
quelle
Keine Sorge, die Verwendung der Anweisung übernimmt die Entsorgung des Objekts.
Dies ist eine Frage aus dem Jahr 2009. Der Wert, jetzt eine Antwort zu geben, wäre also für zukünftige Benutzer, die möglicherweise ähnliche Probleme haben. Antworten auf solche alten Fragen sollten daher nur gegeben werden, wenn sie das Problem eindeutig identifizieren und eine Lösung erklären / liefern können. Es ist normalerweise erfolglos zu versuchen, das OP in ein Gespräch einzubeziehen, da es wahrscheinlich weitergegangen ist.
MikeC
Ich habe all diese Beispiele durchgesehen und mich gefragt, warum ich eine leere Zeichenfolge bekomme. xmlWriter.Close()war die Lösung.
Rafał Ryszkowski
-1

Nun, ich denke, die einfachste und schnellste Lösung wäre hier nur:

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());
}
Deniz
quelle