XmlWriter untuk Menulis ke String, bukan ke File

118

Saya memiliki layanan WCF yang perlu mengembalikan string XML. Tapi sepertinya penulis hanya ingin membangun file, bukan string. Saya mencoba:

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

Ini menghasilkan kesalahan yang mengatakan nextXMLstring tidak memiliki jalur file. Ia menginginkan sesuatu seperti:

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

Bagaimana saya bisa membangun XML saya dan kemudian mengembalikannya sebagai string ??

Terima kasih!!

Api
sumber

Jawaban:

217

Anda perlu membuat StringWriter, dan meneruskannya ke XmlWriter.

Kelebihan string dari XmlWriter.Create adalah untuk nama file.

Misalnya

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


  }
  return sw.ToString();
}
Richard
sumber
2
@Will: Roll back perubahan Anda. XmlTextWriter.Close () akan mengalir ke aliran, jadi ingin hal itu terjadi sebelum mengekstrak string. (Sedikit perbedaan dalam kasus ini, tetapi lebih suka melakukan ini secara konsisten karena semantik flush dari kelas * Penulis dan Aliran tidak selalu didokumentasikan dengan jelas.)
Richard
1
Hanya komentar untuk orang yang menggunakan ini. Jika Anda mengabaikan using () dan sebaliknya mendeklarasikan XmlWriter Anda secara normal, pastikan untuk memanggil xw.Flush sebelum Anda memanggil sw.ToString () atau Anda mungkin tidak mendapatkan semua konten! (Jelas lebih baik menggunakan tanda kurung menggunakan ...)
Ravendarksky
Perlu diingat bahwa kode berikut memberikan peringatan CA2202 selama analisis kode, karena metode Dispose () akan dipanggil dua kali pada objek StringWriter
Łukasz Kosiak
113

Seperti yang dikatakan Richard, StringWriteradalah jalan ke depan. Namun, ada satu halangan: secara default, StringWriterakan mengiklankan dirinya sendiri sebagai UTF-16. Biasanya XML ada dalam UTF-8. Anda dapat memperbaikinya dengan membuat subclass StringWriter;

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

Ini akan mempengaruhi deklarasi yang ditulis oleh XmlWriter. Tentu saja, jika Anda kemudian menulis string di tempat lain dalam bentuk biner, pastikan Anda menggunakan pengkodean yang cocok dengan pengkodean mana pun yang Anda perbaiki untuk StringWriter. (Kode di atas selalu mengasumsikan UTF-8; tidak mudah membuat versi yang lebih umum yang menerima pengkodean dalam konstruktor.)

Anda kemudian akan menggunakan:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}
Jon Skeet
sumber
Jon, apa kau yakin writertidak akan dibuang lebih dari sekali?
rasx
2
@ RASX: Mungkin saja - tapi itu tidak masalah.
Jon Skeet
30

Saya tahu ini sudah tua dan terjawab, tapi ini cara lain untuk melakukannya. Terutama jika Anda tidak ingin UTF8 BOM di awal string Anda dan Anda ingin teks menjorok ke dalam:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}
brianari
sumber
3
Encoding.UTF8.GetString(ms.ToArray())adalah penyederhanaan saat Anda kembali.
SliverNinja - MSFT
1
ms.ToArray()tidak mengembalikan item ketika saya mencoba ini. Harus menambah x.Close()atau memindahkan pernyataan kembali tepat di luar pernyataan menggunakan batin.
Rich C
Apakah utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); kerja?
Brianary
1
@ Rich C - Saya menduga ini karena streaming Anda tidak di-flush. XmlTextWriter akan dibuang di luar pernyataan using-nya yang akan menyebabkannya memudar.
yourbuddypal
15

Penggunaan StringBuilder:

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

Guys jangan lupa untuk memanggil xmlWriter.Close () dan xmlWriter.Dispose () atau string Anda tidak akan selesai dibuat. Itu hanya akan menjadi string kosong

saunupe1911
sumber
Jangan khawatir, menggunakan pernyataan akan menangani pembuangan objek.
Ini adalah pertanyaan dari tahun 2009. Jadi, nilai dalam memberikan jawaban sekarang adalah untuk pengguna di masa mendatang yang mungkin memiliki masalah serupa. Konsekuensinya, jawaban atas pertanyaan lama seperti ini seharusnya hanya diberikan jika mereka dapat mengidentifikasi masalah dengan jelas dan menjelaskan / memberikan solusi. Biasanya sia-sia mencoba melibatkan OP dalam percakapan karena kemungkinan besar mereka sudah pindah.
MikeC
Saya melihat semua contoh ini dan bertanya-tanya mengapa saya mendapatkan string kosong. xmlWriter.Close()adalah solusinya.
Rafał Ryszkowski
-1

Saya pikir solusi termudah dan tercepat di sini adalah hanya dengan:

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
sumber