-1

There are quite a few questions related to this topic that I have browsed through.

But it seems that I have a unique case where we are inheriting a class from XmlTextWriter which makes it impossible to use the XmlWriter.Create() method for instantiating an XmlWriter with XmlWriterSettings.

So the question - Is there a way to specify XmlWriterSettings like OmitXmlDeclaration, DoNotEscapeUriAttributes and CloseOutput for the inherited instance ?

Note: I have used Formatting property in the inherited class but could not locate above mentioned properties unless set through XmlWriterSettings.

  • No. E.g. for `CloseOutput`,If you look at the [reference source for `XmlTextWriter.Close()`](http://referencesource.microsoft.com/#System.Xml/System/Xml/Core/XmlTextWriter.cs,839) the underlying text writer is closed unconditionally. Compare with [`XmlUtf8RawTextWriter.Close()`](http://referencesource.microsoft.com/#System.Xml/System/Xml/Core/XmlUtf8RawTextWriter.cs,587) where the underlying writer is conditionally closed. – dbc Aug 06 '17 at 05:08
  • Have you considered using the decorator pattern to wrap the writer returned from `XmlWriter.Create()` in a decorator, for instance as is shown in [this answer](https://stackoverflow.com/a/42960980) to [How can I stop empty XML elements self-closing using XmlDocument in C#](https://stackoverflow.com/q/42959958)? – dbc Aug 06 '17 at 05:10
  • But for `CloseOutput` you could always construct a `StreamWriter` that does not close the underlying stream, using one of the answers from [Is there any way to close a StreamWriter without closing its BaseStream?](https://stackoverflow.com/q/2666888). – dbc Aug 06 '17 at 05:12
  • @dbc Thanks for the links and the answer below. Will check it out. – Rohit Sahasrabudhe Aug 06 '17 at 05:40
  • Would like to know why the question was downvoted. – Rohit Sahasrabudhe Aug 06 '17 at 05:41
  • Thanks @dbc. Would the person who has downvoted please mention the reason for doing so ? – Rohit Sahasrabudhe Aug 06 '17 at 05:53

1 Answers1

1

XmlTextWriter does not support all the options available in XmlWriterSettings. The class was originally created for writing XML in .Net 1.x and was deprecated in favor of XmlWriter.Create() in .Net 2.0, as explained in the docs:

Starting with the .NET Framework 2.0, we recommend that you use the System.Xml.XmlWriter class instead.

Full support for XmlWriterSettings was never added to the old XmlTextWriter and vice versa. This can be confirmed by checking the reference source.

For instance, for CloseOutput, if you look at the reference source for XmlTextWriter.Close() the underlying text writer is closed unconditionally:

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

Compare with XmlUtf8RawTextWriter.Close() (this class is one of the XML writers returned by XmlWriter.Create()) where the underlying text writer is conditionally closed:

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

(However, you could always construct a StreamWriter that does not close the underlying stream, using one of the answers from Is there any way to close a StreamWriter without closing its BaseStream?.)

Similarly XmlTextWriter.WriteStartDocument() does not appear to have an option to not emit an XML declaration:

    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("?>");
    }

It would seem StartDocument() must needs be called to initialize the writer's internal state, but when called, an XML declaration is always written.

As an alternative, have you considered using the decorator pattern and wrapping the writer returned from XmlWriter.Create() in a decorator, e.g. as is shown in this answer to How can I stop empty XML elements self-closing using XmlDocument in C#? This would allow you to customize your output before passing it to the underlying XmlWriter similarly to how your subclass of XmlTextWriter could customize the output before passing to the base class's methods.

dbc
  • 104,963
  • 20
  • 228
  • 340