File: FrameworkFork\Microsoft.Xml\Xml\Core\XmlWriterSettings.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
// using System.Security.Permissions;
using System.Runtime.Versioning;
 
 
namespace Microsoft.Xml
{
    using System;
 
    public enum XmlOutputMethod
    {
        Xml = 0,    // Use Xml 1.0 rules to serialize
        Html = 1,    // Use Html rules specified by Xslt specification to serialize
        Text = 2,    // Only serialize text blocks
        AutoDetect = 3,    // Choose between Xml and Html output methods at runtime (using Xslt rules to do so)
    }
 
    /// <summary>
    /// Three-state logic enumeration.
    /// </summary>
    internal enum TriState
    {
        Unknown = -1,
        False = 0,
        True = 1,
    };
 
    internal enum XmlStandalone
    {
        // Do not change the constants - XmlBinaryWriter depends in it
        Omit = 0,
        Yes = 1,
        No = 2,
    }
 
    // XmlWriterSettings class specifies basic features of an XmlWriter.
    public sealed class XmlWriterSettings
    {
        //
        // Fields
        //
 
        // Text settings
        private Encoding _encoding;
 
        private bool _omitXmlDecl;
        private NewLineHandling _newLineHandling;
        private string _newLineChars;
        private TriState _indent;
        private string _indentChars;
        private bool _newLineOnAttributes;
        private bool _closeOutput;
        private NamespaceHandling _namespaceHandling;
 
        // Conformance settings
        private ConformanceLevel _conformanceLevel;
        private bool _checkCharacters;
        private bool _writeEndDocumentOnClose;
 
        // Xslt settings
        private XmlOutputMethod _outputMethod;
        private List<XmlQualifiedName> _cdataSections = new List<XmlQualifiedName>();
        private bool _doNotEscapeUriAttributes;
        private bool _mergeCDataSections;
        private string _mediaType;
        private string _docTypeSystem;
        private string _docTypePublic;
        private XmlStandalone _standalone;
        private bool _autoXmlDecl;
 
        // read-only flag
        private bool _isReadOnly;
 
        //
        // Constructor
        //
        public XmlWriterSettings()
        {
            Initialize();
        }
 
        //
        // Properties
        //
 
        // Text
        public Encoding Encoding
        {
            get
            {
                return _encoding;
            }
            set
            {
                CheckReadOnly("Encoding");
                _encoding = value;
            }
        }
 
        // True if an xml declaration should *not* be written.
        public bool OmitXmlDeclaration
        {
            get
            {
                return _omitXmlDecl;
            }
            set
            {
                CheckReadOnly("OmitXmlDeclaration");
                _omitXmlDecl = value;
            }
        }
 
        // See NewLineHandling enum for details.
        public NewLineHandling NewLineHandling
        {
            get
            {
                return _newLineHandling;
            }
            set
            {
                CheckReadOnly("NewLineHandling");
 
                if ((uint)value > (uint)NewLineHandling.None)
                {
                    throw new ArgumentOutOfRangeException("value");
                }
                _newLineHandling = value;
            }
        }
 
        // Line terminator string. By default, this is a carriage return followed by a line feed ("\r\n").
        public string NewLineChars
        {
            get
            {
                return _newLineChars;
            }
            set
            {
                CheckReadOnly("NewLineChars");
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                _newLineChars = value;
            }
        }
 
        // True if output should be indented using rules that are appropriate to the output rules (i.e. Xml, Html, etc).
        public bool Indent
        {
            get
            {
                return _indent == TriState.True;
            }
            set
            {
                CheckReadOnly("Indent");
                _indent = value ? TriState.True : TriState.False;
            }
        }
 
        // Characters to use when indenting. This is usually tab or some spaces, but can be anything.
        public string IndentChars
        {
            get
            {
                return _indentChars;
            }
            set
            {
                CheckReadOnly("IndentChars");
 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                _indentChars = value;
            }
        }
 
        // Whether or not indent attributes on new lines.
        public bool NewLineOnAttributes
        {
            get
            {
                return _newLineOnAttributes;
            }
            set
            {
                CheckReadOnly("NewLineOnAttributes");
                _newLineOnAttributes = value;
            }
        }
 
        // Whether or not the XmlWriter should close the underlying stream or TextWriter when Close is called on the XmlWriter.
        public bool CloseOutput
        {
            get
            {
                return _closeOutput;
            }
            set
            {
                CheckReadOnly("CloseOutput");
                _closeOutput = value;
            }
        }
 
 
        // Conformance
        // See ConformanceLevel enum for details.
        public ConformanceLevel ConformanceLevel
        {
            get
            {
                return _conformanceLevel;
            }
            set
            {
                CheckReadOnly("ConformanceLevel");
 
                if ((uint)value > (uint)ConformanceLevel.Document)
                {
                    throw new ArgumentOutOfRangeException("value");
                }
                _conformanceLevel = value;
            }
        }
 
        // Whether or not to check content characters that they are valid XML characters.
        public bool CheckCharacters
        {
            get
            {
                return _checkCharacters;
            }
            set
            {
                CheckReadOnly("CheckCharacters");
                _checkCharacters = value;
            }
        }
 
        // Whether or not to remove duplicate namespace declarations
        public NamespaceHandling NamespaceHandling
        {
            get
            {
                return _namespaceHandling;
            }
            set
            {
                CheckReadOnly("NamespaceHandling");
                if ((uint)value > (uint)(NamespaceHandling.OmitDuplicates))
                {
                    throw new ArgumentOutOfRangeException("value");
                }
                _namespaceHandling = value;
            }
        }
 
        //Whether or not to auto complete end-element when close/dispose
        public bool WriteEndDocumentOnClose
        {
            get
            {
                return _writeEndDocumentOnClose;
            }
            set
            {
                CheckReadOnly("WriteEndDocumentOnClose");
                _writeEndDocumentOnClose = value;
            }
        }
 
        // Specifies the method (Html, Xml, etc.) that will be used to serialize the result tree.
        public XmlOutputMethod OutputMethod
        {
            get
            {
                return _outputMethod;
            }
            internal set
            {
                _outputMethod = value;
            }
        }
 
        //
        // Public methods
        //
        public void Reset()
        {
            CheckReadOnly("Reset");
            Initialize();
        }
 
        // Deep clone all settings (except read-only, which is always set to false).  The original and new objects
        // can now be set independently of each other.
        public XmlWriterSettings Clone()
        {
            XmlWriterSettings clonedSettings = MemberwiseClone() as XmlWriterSettings;
 
            // Deep clone shared settings that are not immutable
            clonedSettings._cdataSections = new List<XmlQualifiedName>(_cdataSections);
 
            clonedSettings._isReadOnly = false;
            return clonedSettings;
        }
 
        //
        // Internal properties
        //
        // Set of XmlQualifiedNames that identify any elements that need to have text children wrapped in CData sections.
        internal List<XmlQualifiedName> CDataSectionElements
        {
            get
            {
                Debug.Assert(_cdataSections != null);
                return _cdataSections;
            }
        }
 
        // Used in Html writer to disable encoding of uri attributes
        public bool DoNotEscapeUriAttributes
        {
            get
            {
                return _doNotEscapeUriAttributes;
            }
            set
            {
                CheckReadOnly("DoNotEscapeUriAttributes");
                _doNotEscapeUriAttributes = value;
            }
        }
 
        internal bool MergeCDataSections
        {
            get
            {
                return _mergeCDataSections;
            }
            set
            {
                CheckReadOnly("MergeCDataSections");
                _mergeCDataSections = value;
            }
        }
 
        // Used in Html writer when writing Meta element.  Null denotes the default media type.
        internal string MediaType
        {
            get
            {
                return _mediaType;
            }
            set
            {
                CheckReadOnly("MediaType");
                _mediaType = value;
            }
        }
 
        // System Id in doc-type declaration.  Null denotes the absence of the system Id.
        internal string DocTypeSystem
        {
            get
            {
                return _docTypeSystem;
            }
            set
            {
                CheckReadOnly("DocTypeSystem");
                _docTypeSystem = value;
            }
        }
 
        // Public Id in doc-type declaration.  Null denotes the absence of the public Id.
        internal string DocTypePublic
        {
            get
            {
                return _docTypePublic;
            }
            set
            {
                CheckReadOnly("DocTypePublic");
                _docTypePublic = value;
            }
        }
 
        // Yes for standalone="yes", No for standalone="no", and Omit for no standalone.
        internal XmlStandalone Standalone
        {
            get
            {
                return _standalone;
            }
            set
            {
                CheckReadOnly("Standalone");
                _standalone = value;
            }
        }
 
        // True if an xml declaration should automatically be output (no need to call WriteStartDocument)
        internal bool AutoXmlDeclaration
        {
            get
            {
                return _autoXmlDecl;
            }
            set
            {
                CheckReadOnly("AutoXmlDeclaration");
                _autoXmlDecl = value;
            }
        }
 
        // If TriState.Unknown, then Indent property was not explicitly set.  In this case, the AutoDetect output
        // method will default to Indent=true for Html and Indent=false for Xml.
        internal TriState IndentInternal
        {
            get
            {
                return _indent;
            }
            set
            {
                _indent = value;
            }
        }
 
        internal bool IsQuerySpecific
        {
            get
            {
                return _cdataSections.Count != 0 || _docTypePublic != null ||
                       _docTypeSystem != null || _standalone == XmlStandalone.Yes;
            }
        }
 
        // [ResourceConsumption(ResourceScope.Machine)]
        // [ResourceExposure(ResourceScope.Machine)]
        internal XmlWriter CreateWriter(string outputFileName)
        {
            if (outputFileName == null)
            {
                throw new ArgumentNullException("outputFileName");
            }
 
            // need to clone the settigns so that we can set CloseOutput to true to make sure the stream gets closed in the end
            XmlWriterSettings newSettings = this;
            if (!newSettings.CloseOutput)
            {
                newSettings = newSettings.Clone();
                newSettings.CloseOutput = true;
            }
 
            FileStream fs = null;
            try
            {
                // open file stream
                fs = new FileStream(outputFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
 
                // create writer
                return newSettings.CreateWriter(fs);
            }
            catch
            {
                if (fs != null)
                {
                    fs.Close();
                }
                throw;
            }
        }
 
        internal XmlWriter CreateWriter(Stream output)
        {
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }
 
            XmlWriter writer;
 
            // create raw writer
 
            Debug.Assert(Encoding.UTF8.WebName == "utf-8");
            if (this.Encoding.WebName == "utf-8")
            { // Encoding.CodePage is not supported in Silverlight
                // create raw UTF-8 writer
                switch (this.OutputMethod)
                {
                    case XmlOutputMethod.Xml:
                        if (this.Indent)
                        {
                            writer = new XmlUtf8RawTextWriterIndent(output, this);
                        }
                        else
                        {
                            writer = new XmlUtf8RawTextWriter(output, this);
                        }
                        break;
                    case XmlOutputMethod.Html:
                        if (this.Indent)
                        {
                            writer = new HtmlUtf8RawTextWriterIndent(output, this);
                        }
                        else
                        {
                            writer = new HtmlUtf8RawTextWriter(output, this);
                        }
                        break;
                    case XmlOutputMethod.Text:
                        writer = new TextUtf8RawTextWriter(output, this);
                        break;
                    case XmlOutputMethod.AutoDetect:
                        writer = new XmlAutoDetectWriter(output, this);
                        break;
                    default:
                        Debug.Assert(false, "Invalid XmlOutputMethod setting.");
                        return null;
                }
            }
            else
            {
                // Otherwise, create a general-purpose writer than can do any encoding
                switch (this.OutputMethod)
                {
                    case XmlOutputMethod.Xml:
                        if (this.Indent)
                        {
                            writer = new XmlEncodedRawTextWriterIndent(output, this);
                        }
                        else
                        {
                            writer = new XmlEncodedRawTextWriter(output, this);
                        }
                        break;
                    case XmlOutputMethod.Html:
                        if (this.Indent)
                        {
                            writer = new HtmlEncodedRawTextWriterIndent(output, this);
                        }
                        else
                        {
                            writer = new HtmlEncodedRawTextWriter(output, this);
                        }
                        break;
                    case XmlOutputMethod.Text:
                        writer = new TextEncodedRawTextWriter(output, this);
                        break;
                    case XmlOutputMethod.AutoDetect:
                        writer = new XmlAutoDetectWriter(output, this);
                        break;
                    default:
                        Debug.Assert(false, "Invalid XmlOutputMethod setting.");
                        return null;
                }
            }
 
            // Wrap with Xslt/XQuery specific writer if needed; 
            // XmlOutputMethod.AutoDetect writer does this lazily when it creates the underlying Xml or Html writer.
            if (this.OutputMethod != XmlOutputMethod.AutoDetect)
            {
                if (this.IsQuerySpecific)
                {
                    // Create QueryOutputWriter if CData sections or DocType need to be tracked
                    writer = new QueryOutputWriter((XmlRawWriter)writer, this);
                }
            }
 
            // wrap with well-formed writer
            writer = new XmlWellFormedWriter(writer, this);
 
            return writer;
        }
 
        internal XmlWriter CreateWriter(TextWriter output)
        {
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }
 
            XmlWriter writer;
 
            // create raw writer
            switch (this.OutputMethod)
            {
                case XmlOutputMethod.Xml:
                    if (this.Indent)
                    {
                        writer = new XmlEncodedRawTextWriterIndent(output, this);
                    }
                    else
                    {
                        writer = new XmlEncodedRawTextWriter(output, this);
                    }
                    break;
                case XmlOutputMethod.Html:
                    if (this.Indent)
                    {
                        writer = new HtmlEncodedRawTextWriterIndent(output, this);
                    }
                    else
                    {
                        writer = new HtmlEncodedRawTextWriter(output, this);
                    }
                    break;
                case XmlOutputMethod.Text:
                    writer = new TextEncodedRawTextWriter(output, this);
                    break;
                case XmlOutputMethod.AutoDetect:
                    writer = new XmlAutoDetectWriter(output, this);
                    break;
                default:
                    Debug.Assert(false, "Invalid XmlOutputMethod setting.");
                    return null;
            }
 
            // XmlOutputMethod.AutoDetect writer does this lazily when it creates the underlying Xml or Html writer.
            if (this.OutputMethod != XmlOutputMethod.AutoDetect)
            {
                if (this.IsQuerySpecific)
                {
                    // Create QueryOutputWriter if CData sections or DocType need to be tracked
                    writer = new QueryOutputWriter((XmlRawWriter)writer, this);
                }
            }
 
            // wrap with well-formed writer
            writer = new XmlWellFormedWriter(writer, this);
 
            return writer;
        }
 
        internal XmlWriter CreateWriter(XmlWriter output)
        {
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }
 
            return AddConformanceWrapper(output);
        }
 
 
        internal bool ReadOnly
        {
            get
            {
                return _isReadOnly;
            }
            set
            {
                _isReadOnly = value;
            }
        }
 
        private void CheckReadOnly(string propertyName)
        {
            if (_isReadOnly)
            {
                throw new XmlException(ResXml.Xml_ReadOnlyProperty, this.GetType().Name + '.' + propertyName);
            }
        }
 
        //
        // Private methods
        //
        private void Initialize()
        {
            _encoding = Encoding.UTF8;
            _omitXmlDecl = false;
            _newLineHandling = NewLineHandling.Replace;
            _newLineChars = Environment.NewLine; // "\r\n" on Windows, "\n" on Unix
            _indent = TriState.Unknown;
            _indentChars = "  ";
            _newLineOnAttributes = false;
            _closeOutput = false;
            _namespaceHandling = NamespaceHandling.Default;
            _conformanceLevel = ConformanceLevel.Document;
            _checkCharacters = true;
            _writeEndDocumentOnClose = true;
 
            _outputMethod = XmlOutputMethod.Xml;
            _cdataSections.Clear();
            _mergeCDataSections = false;
            _mediaType = null;
            _docTypeSystem = null;
            _docTypePublic = null;
            _standalone = XmlStandalone.Omit;
            _doNotEscapeUriAttributes = false;
 
            _isReadOnly = false;
        }
 
        private XmlWriter AddConformanceWrapper(XmlWriter baseWriter)
        {
            ConformanceLevel confLevel = ConformanceLevel.Auto;
            XmlWriterSettings baseWriterSettings = baseWriter.Settings;
            bool checkValues = false;
            bool checkNames = false;
            bool replaceNewLines = false;
            bool needWrap = false;
 
            if (baseWriterSettings == null)
            {
                // assume the V1 writer already do all conformance checking; 
                // wrap only if NewLineHandling == Replace or CheckCharacters is true
                if (_newLineHandling == NewLineHandling.Replace)
                {
                    replaceNewLines = true;
                    needWrap = true;
                }
                if (_checkCharacters)
                {
                    checkValues = true;
                    needWrap = true;
                }
            }
            else
            {
                if (_conformanceLevel != baseWriterSettings.ConformanceLevel)
                {
                    confLevel = this.ConformanceLevel;
                    needWrap = true;
                }
                if (_checkCharacters && !baseWriterSettings.CheckCharacters)
                {
                    checkValues = true;
                    checkNames = confLevel == ConformanceLevel.Auto;
                    needWrap = true;
                }
                if (_newLineHandling == NewLineHandling.Replace &&
                     baseWriterSettings.NewLineHandling == NewLineHandling.None)
                {
                    replaceNewLines = true;
                    needWrap = true;
                }
            }
 
            XmlWriter writer = baseWriter;
 
            if (needWrap)
            {
                if (confLevel != ConformanceLevel.Auto)
                {
                    writer = new XmlWellFormedWriter(writer, this);
                }
                if (checkValues || replaceNewLines)
                {
                    writer = new XmlCharCheckingWriter(writer, checkValues, checkNames, replaceNewLines, this.NewLineChars);
                }
            }
 
            if (this.IsQuerySpecific && (baseWriterSettings == null || !baseWriterSettings.IsQuerySpecific))
            {
                // Create QueryOutputWriterV1 if CData sections or DocType need to be tracked
                writer = new QueryOutputWriterV1(writer, this);
            }
 
            return writer;
        }
 
        //
        // Internal methods
        //
        internal void GetObjectData(object writer) { }
        internal XmlWriterSettings(object reader) { }
    }
}