XmlWriter для запису до рядка замість файлу


118

У мене є служба WCF, якій потрібно повернути рядок XML. Але схоже, що письменник хоче створити лише файл, а не рядок. Я намагався:

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

Це створює помилку, кажучи, що nextXMLstring не має шлях до файлу. Він хоче щось подібне:

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

Як я можу створити свій XML, а потім повернути його як рядок ??

Дякую!!

Відповіді:


217

Вам потрібно створити StringWriter і передати його XmlWriter.

Перевантаження рядка XmlWriter.Create призначене для імені файлу.

Напр

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


  }
  return sw.ToString();
}

2
@Will: повернув свої зміни. XmlTextWriter.Close () буде передаватися потоку, тому хочете, щоб це сталося перед вилученням рядка. (Незначна різниця в цьому випадку, але вважайте за краще це робити послідовно, оскільки флемантика сеансів класів * Writer і Stream не завжди чітко зафіксована.)
Річард,

1
Просто коментар для людей, які використовують це. Якщо ви втрачаєте використання () і замість цього декларуєте свій XmlWriter звичайно, тоді обов'язково зателефонуйте на xw.Flush, перш ніж зателефонувати sw.ToString (), інакше ви не зможете отримати весь вміст! (Очевидно, краще скористатися скористаються дужками ...)
Равендарський

Майте на увазі, що наступний код дає попередження CA2202 під час аналізу коду, тому що метод об’єкта Dispose () буде викликаний двічі на об’єкт StringWriter
Łukasz Kosiak

113

Як сказав Річард, StringWriterце шлях вперед. Однак є один корч: за замовчуванням StringWriterрекламує себе як UTF-16. Зазвичай XML знаходиться в UTF-8. Ви можете виправити це за допомогою підкласингу StringWriter;

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

Це вплине на декларацію, написану XmlWriter. Звичайно, якщо ви потім запишете рядок в іншому місці у двійковій формі, переконайтеся, що ви використовуєте кодування, яке відповідає тому, яке кодування ви встановите StringWriter. (Вищевказаний код завжди передбачає UTF-8; тривіально робити більш загальну версію, яка приймає кодування в конструкторі.)

Потім ви будете використовувати:

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

Джон, ти впевнений, що writerйого не розміщують більше одного разу?
rasx

2
@rasx: Це може бути - але це не має значення.
Джон Скіт

30

Я знаю, що це старе і відповіли, але ось ще один спосіб зробити це. Особливо, якщо ви не хочете, щоб BT UTF8 BOM на початку рядка, і ви хочете текст з відступом:

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())- це спрощення при поверненні.
SliverNinja - MSFT

1
ms.ToArray()не повертає жодних предметів, коли я спробував це. Довелося додати x.Close()або перемістити оператор return просто за межами внутрішнього використання оператора.
Rich C

Чи utf8.GetString (ms.GetBuffer (), 0, (int) ms.Length); робота?
бріанарій

1
@Rich C - Я підозрюю, що це тому, що ваш потік не був промитий. XmlTextWriter був би розміщений поза його оператором використання, що призведе до його змивання.
yourbuddypal

13

Використання StringBuilder:

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

1

Хлопці не забудьте зателефонувати на xmlWriter.Close () та xmlWriter.Dispose (), інакше ваша строка не закінчить створювати. Це буде просто порожня рядок


Не хвилюйтесь, за допомогою оператора обробка об’єкта розпоряджається.

Це питання з 2009 року. Отже, значення надання відповіді зараз було б для майбутніх користувачів, які можуть мати подібні проблеми. Отже, відповіді на старі подібні питання слід надати лише у тому випадку, якщо вони можуть чітко визначити проблему та пояснити / запропонувати рішення. Як правило, безрезультатно намагатися вступити з ОП у розмову, оскільки вони, ймовірно, продовжують свою діяльність.
MikeC

Я переглядав усі ці приклади і цікавився, чому я отримую порожню рядок. xmlWriter.Close()було рішенням.
Rafał Ryszkowski

-1

Ну, я думаю, найпростішим і швидким рішенням було б просто:

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());
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.