Унаследованный XmlTextWriter с XmlWriterSettings

Есть довольно много вопросов, связанных с этой темой, которую я просмотрел.

Но, похоже, у меня есть уникальный случай, когда мы наследуем класс от XmlTextWriter, что делает невозможным использование метода XmlWriter.Create() для создания экземпляра XmlWriter с XmlWriterSettings.

Итак, вопрос: есть ли способ указать XmlWriterSettings, такие как OmitXmlDeclaration, DoNotEscapeUriAttributes и CloseOutput, для унаследованного экземпляра?

Примечание. Я использовал свойство Formatting в унаследованном классе, но не смог найти вышеупомянутые свойства, если они не установлены через XmlWriterSettings.


person Rohit Sahasrabudhe    schedule 06.08.2017    source источник
comment
№ для CloseOutput, если вы посмотрите на справочный источник для XmlTextWriter.Close() основной модуль записи текста закрыт безоговорочно. Сравните с XmlUtf8RawTextWriter.Close(), где основной модуль записи условно закрытый.   -  person dbc    schedule 06.08.2017
comment
Рассматривали ли вы использование шаблона декоратора для переноса возвращаемого из XmlWriter.Create() средства записи в декоратор, например, как показано в этом ответе на Как остановить самозакрытие пустых XML-элементов с помощью XmlDocument в C#?   -  person dbc    schedule 06.08.2017
comment
Но для CloseOutput вы всегда можете создать StreamWriter, который не закрывает базовый поток, используя один из ответов из Есть ли способ закрыть StreamWriter без закрыть свой BaseStream?.   -  person dbc    schedule 06.08.2017
comment
@dbc Спасибо за ссылки и ответ ниже. Проверим.   -  person Rohit Sahasrabudhe    schedule 06.08.2017
comment
Хотелось бы знать, почему вопрос был отклонен.   -  person Rohit Sahasrabudhe    schedule 06.08.2017
comment
Спасибо @dbc. Не мог бы человек, который проголосовал против, указать причину этого?   -  person Rohit Sahasrabudhe    schedule 06.08.2017


Ответы (1)


XmlTextWriter не поддерживает все параметры, доступные в XmlWriterSettings. Первоначально этот класс был создан для записи XML в .Net 1.x и устарел в пользу XmlWriter.Create() в .Net 2.0, как описано в документы:

Начиная с .NET Framework 2.0, вместо этого рекомендуется использовать класс System.Xml.XmlWriter.

Полная поддержка XmlWriterSettings никогда не добавлялась к старому XmlTextWriter и наоборот. В этом можно убедиться, проверив справочный источник.

Например, для CloseOutput, если вы посмотрите на справочный источник для XmlTextWriter.Close() основного модуля записи текста закрыт безоговорочно:

    public override void Close() {
        try {
            AutoCompleteAll();
        } 
        catch { // never fail
        } 
        finally {
            this.currentState = State.Closed;
            textWriter.Close();
        }
    }

Сравните с XmlUtf8RawTextWriter.Close() (этот класс один из модулей записи XML, возвращенных XmlWriter.Create()), где базовый модуль записи текста условно закрыт:

    public override void Close() {
        try {
            FlushBuffer();
            FlushEncoder();
        }
        finally {
            // Future calls to Close or Flush shouldn't write to Stream or Writer
            writeToNull = true;

            if ( stream != null ) {
                try {
                    stream.Flush();
                }
                finally {
                    try {
                        if ( closeOutput ) {
                            stream.Close();
                        }
                    }
                    finally {
                        stream = null;
                    }
                }
            }
        }
    }

(Однако вы всегда можете создать StreamWriter, который не закрывает базовый поток, используя один из ответов из Есть ли способ закрыть StreamWriter без закрывает свой BaseStream?.)

Аналогично XmlTextWriter.WriteStartDocument() не имеет возможность не создавать XML-декларацию:

    public override void WriteStartDocument() {
        StartDocument(-1);
    }

    // Writes out the XML declaration with the version "1.0" and the standalone attribute.
    public override void WriteStartDocument(bool standalone) {
        StartDocument(standalone ? 1 : 0);
    }

    void StartDocument(int standalone) {
        try {
            if (this.currentState != State.Start) {
                throw new InvalidOperationException(Res.GetString(Res.Xml_NotTheFirst));
            }
            this.stateTable = stateTableDocument;
            this.currentState = State.Prolog;

            StringBuilder bufBld = new StringBuilder(128);
            bufBld.Append("version=" + quoteChar + "1.0" + quoteChar);
            if (this.encoding != null) {
                bufBld.Append(" encoding=");
                bufBld.Append(quoteChar);
                bufBld.Append(this.encoding.WebName);
                bufBld.Append(quoteChar);
            }
            if (standalone >= 0) {
                bufBld.Append(" standalone=");
                bufBld.Append(quoteChar);
                bufBld.Append(standalone == 0 ? "no" : "yes");
                bufBld.Append(quoteChar);
            }
            InternalWriteProcessingInstruction("xml", bufBld.ToString());
        }
        catch {
            currentState = State.Error;
            throw;
        }
    }

    void InternalWriteProcessingInstruction(string name, string text) {
        textWriter.Write("<?");
        ValidateName(name, false);
        textWriter.Write(name);
        textWriter.Write(' ');
        if (null != text) {
            xmlEncoder.WriteRawWithSurrogateChecking(text);
        }
        textWriter.Write("?>");
    }

Казалось бы, StartDocument() необходимо вызывать для инициализации внутреннего состояния модуля записи, но при вызове всегда записывается XML-декларация.

В качестве альтернативы вы не рассматривали возможность использования шаблона декоратора и переноса средства записи, возвращенного из XmlWriter.Create(), в декоратор, например как показано в этом ответе на Как я могу остановить самозакрытие пустых элементов XML с помощью XmlDocument в C#? Это позволит вам настроить вывод перед передачей его в базовый XmlWriter аналогично тому, как ваш подкласс XmlTextWriter может настроить вывод перед передачей в методы базового класса.

person dbc    schedule 06.08.2017