【问题标题】:Inherited XmlTextWriter with XmlWriterSettings使用 XmlWriterSettings 继承 XmlTextWriter
【发布时间】:2017-08-06 04:41:50
【问题描述】:

我浏览过很多与这个主题相关的问题。

但似乎我有一个独特的情况,我们从 XmlTextWriter 继承一个类,这使得无法使用 XmlWriter.Create() 方法通过 XmlWriterSettings 实例化 XmlWriter。

所以问题 - 有没有办法为继承的实例指定 XmlWriterSettings,如 OmitXmlDeclaration、DoNotEscapeUriAttributes 和 CloseOutput?

注意:我在继承类中使用了 Formatting 属性,但无法找到上述属性,除非通过 XmlWriterSettings 设置。

【问题讨论】:

标签: c# .net xml inheritance xmlwriter


【解决方案1】:

XmlTextWriter 不支持XmlWriterSettings 中的所有选项。该类最初是为在 .Net 1.x 中编写 XML 而创建的,但在 .Net 2.0 中已弃用 XmlWriter.Create(),如 docs 中所述:

从 .NET Framework 2.0 开始,我们建议您改用 System.Xml.XmlWriter 类。

XmlWriterSettings 的完全支持从未添加到旧的XmlTextWriter 中,反之亦然。这可以通过检查参考源来确认。

例如,对于CloseOutput,如果您查看reference source for XmlTextWriter.Close(),则底层文本编写器将无条件关闭:

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

XmlUtf8RawTextWriter.Close()(此类是XmlWriter.Create() 返回的XML 编写器之一)比较,其中底层文本编写器有条件地关闭:

    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;
                    }
                }
            }
        }
    }

(但是,您始终可以使用Is there any way to close a StreamWriter without closing its BaseStream? 的答案之一构造一个不关闭底层流的StreamWriter。)

同样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 声明。

作为替代方案,您是否考虑过使用 decorator pattern 并将从 XmlWriter.Create() 返回的编写器包装在装饰器中,例如如this answerHow can I stop empty XML elements self-closing using XmlDocument in C# 所示?这将允许您在将输出传递给底层 XmlWriter 之前对其进行自定义,类似于您的 XmlTextWriter 的子类可以在传递给基类的方法之前自定义输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 2018-05-23
    • 2019-04-26
    相关资源
    最近更新 更多