Повторное использование класса XmlTextWriter

Можно ли повторно использовать один и тот же экземпляр класса XmlTextWriter для создания большего количества XML-документов? Я имею в виду что-то вроде этого:

XmlTextWriter writer = new XmlTextWriter();
writer.WriteStartDocument();
writer.WriteStartElement("Message1");
writer.WriteEndElement();
writer.WriteEndDocument();

// do something with xml created
...

writer.Reset() // ?
writer.WriteStartDocument();
writer.WriteStartElement("Message2");
writer.WriteEndElement();
writer.WriteEndDocument();
// do something with xml created
...

3 ответа

Решение

Простой ответ: да, это возможно.

Но это будет достигнуто, если основной поток не указывает на файл. MemoryStream может быть хорошим примером этого.

Так как MemoryStream сохраняет поток "в памяти", вы можете написать множество XML-файлов с помощью вашего XmlTextWriter и после завершения каждого документа выполнить MemoryStream.ToArray() и передать его в качестве аргумента для File.WriteAllBytes.

После записи всех байтов вы очистите поток памяти.

Вы можете очистить поток памяти, вызвав метод MemoryStream.SetLength и указав 0 в качестве длины:

Подробнее о перегрузке потока в конструкторе XmlTextWriter читайте здесь:

И это для File.WriteAllBytes:

О некоторых проблемах при повторном использовании XmlTextWriter

Несколько лет назад @NigelTouch выразил обеспокоенность по поводу некоторых комментариев:

Проблема, которую я обнаружил, состоит в том, что если исключение выдается на полпути, например, после WriteStartElement(), то даже если вы Flush() Writer и установите длину потока равной 0, Writer остается в WriteState элемента. Когда вы начинаете следующий документ, он начинается с закрывающего ">" (например). Избегайте повторного использования

И несколько часов назад @Mike-EEE попал в ту же проблему:

Пожалуйста, предоставьте рабочий код примера решения. Я сталкиваюсь с той же проблемой, как описывает Найджел

Кстати, немного пробных ошибок заставило меня восстановить данные XmlTextWriter использовать его столько раз, сколько вы хотите:

    using(MemoryStream stream = new MemoryStream())
    using(StreamReader streamReader = new StreamReader(stream))
    using(XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8))
    {
        writer.WriteStartDocument(true);
        writer.WriteStartElement("a");

        try 
        {
            throw new Exception();
        }
        catch 
        {
            // This line makes de magic: ending the document
            // avoids the issue mentioned by @NigelTouch
            writer.WriteEndDocument();
            writer.Flush();
            stream.SetLength(0);
        }


        writer.WriteStartDocument(true);
        writer.WriteStartElement("b");
        writer.WriteEndElement();
        writer.Flush();

        stream.Position = 0;

        Console.WriteLine(streamReader.ReadToEnd());

    }

XmlTextWriter учебный класс:

Представляет средство записи, обеспечивающее быстрый, не кэшированный, прямой способ генерирования потоков или файлов, содержащих данные XML, который соответствует расширяемому языку разметки W3C (XML) 1.0 и пространствам имен в рекомендациях XML.

(акцент мой)

Класс не предоставляет Reset или любой подобной функции, и при этом это не дает доступ к базовому потоку. Если у вас есть доступ к базовому потоку самостоятельно, вы можете сбросить этот поток самостоятельно.

Все это означает, что невозможно повторно использовать его напрямую.

Я предполагаю, что flush сделает примерно то, что вы просите. Просто создайте и получите XML, очистите, запустите, повторите;)

Приветствия.

Другие вопросы по тегам