使用XmlWriterSettings继承XmlTextWriter

时间:2017-08-06 04:41:51

标签: c# .net xml inheritance xmlwriter

我浏览了很多与此主题相关的问题。

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

所以问题 - 是否有办法为继承的实例指定XmitWriterSettings,如OmitXmlDeclaration,DoNotEscapeUriAttributes和CloseOutput?

注意:我在继承的类中使用了Formatting属性,但除非通过XmlWriterSettings设置,否则找不到上面提到的属性。

1 个答案:

答案 0 :(得分:0)

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的子类在传递给基类的方法之前可以自定义输出。