XmlUtil.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Configuration / System / Configuration / XmlUtil.cs / 1 / XmlUtil.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Configuration { 
    using System.Configuration.Internal; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Collections.Generic;
    using System.Configuration;
    using System.Globalization;
    using System.IO; 
    using System.Runtime.InteropServices;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Text;
    using System.Xml; 
    using System.Net;

    //
    // XmlTextReader Helper class. 
    //
    // Provides the following services: 
    // 
    //      * Reader methods that verify restrictions on the XML that can be contained in a config file.
    //      * Methods to copy the reader stream to a writer stream. 
    //      * Method to copy a configuration section to a string.
    //      * Methods to format a string of XML.
    //
    // Errors found during read are accumlated in a ConfigurationSchemaErrors object. 
    //
    internal sealed class XmlUtil : IDisposable, IConfigErrorInfo 
    { 
        private const int   MAX_LINE_WIDTH=60;
 
        // Offset from where the reader reports the LinePosition of an Xml Node to
        // the start of that representation in text.
        static readonly int[] s_positionOffset = {
            0,      // None, 
            1,      // Element,                 
            -1,     // EndEntity,               N/A
            2,      // XmlDeclaration            0, "trueLinePosition > 0");
                return trueLinePosition; 
            }
        } 
 
        internal XmlTextReader Reader {
            get { return _reader; } 
        }

        internal ConfigurationSchemaErrors SchemaErrors {
            get { return _schemaErrors; } 
        }
 
        // 
        // Read until the Next Element element, or we hit
        // the end of the file. 
        //
        internal void ReadToNextElement() {
            while (_reader.Read()) {
                if (_reader.MoveToContent() == XmlNodeType.Element) { 
                    // We found an element, so return
                    return; 
                } 
            }
 
            // We must of hit end of file
        }

        // 
        // Skip this element and its children, then read to next start element,
        // or until we hit end of file. 
        // 
        internal void SkipToNextElement() {
            _reader.Skip(); 
            _reader.MoveToContent();

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.Element) {
                _reader.Read(); 
                _reader.MoveToContent();
            } 
        } 

        // 
        // Read to the next start element, and verify that all XML nodes read are permissible.
        //
        internal void StrictReadToNextElement(ExceptionAction action) {
            while (_reader.Read()) { 
                // optimize for the common case
                if (_reader.NodeType == XmlNodeType.Element) { 
                    return; 
                }
 
                VerifyIgnorableNodeType(action);
            }
        }
 
        //
        // Skip this element and its children, then read to next start element, 
        // or until we hit end of file. Verify that nodes that are read after the 
        // skipped element are permissible.
        // 
        internal void StrictSkipToNextElement(ExceptionAction action) {
            _reader.Skip();

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.Element) { 
                VerifyIgnorableNodeType(action);
                _reader.Read(); 
            } 
        }
 
        //
        // StrictSkipToOurParentsEndElement
        //
        // Skip until we hit the end element for our parent, and verify 
        // that nodes at the parent level are permissible.
        // 
        internal void StrictSkipToOurParentsEndElement(ExceptionAction action) { 
            int currentDepth = _reader.Depth;
 
            // Skip everything at out current level
            while (_reader.Depth >= currentDepth) {
                _reader.Skip();
            } 

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.EndElement) { 
                VerifyIgnorableNodeType(action); 
                _reader.Read();
            } 
        }

        //
        // Add an error if the node type is not permitted by the configuration schema. 
        //
        internal void VerifyIgnorableNodeType(ExceptionAction action) { 
            XmlNodeType nodeType = _reader.NodeType; 

            if (nodeType != XmlNodeType.Comment && nodeType != XmlNodeType.EndElement) { 
                ConfigurationException ex = new ConfigurationErrorsException(
                    SR.GetString(SR.Config_base_unrecognized_element),
                    this);
 
                SchemaErrors.AddError(ex, action);
            } 
        } 

        // 
        // Add an error if there are attributes that have not been examined,
        // and are therefore unrecognized.
        //
        internal void VerifyNoUnrecognizedAttributes(ExceptionAction action) { 
            if (_reader.MoveToNextAttribute()) {
                AddErrorUnrecognizedAttribute(action); 
            } 
        }
 
        //
        // Add an error if the retrieved attribute is null,
        // and therefore not present.
        // 
        internal bool VerifyRequiredAttribute(
                object o, string attrName, ExceptionAction action) { 
 
            if (o == null) {
                AddErrorRequiredAttribute(attrName, action); 
                return false;
            }
            else {
                return true; 
            }
        } 
 
        //
        // Functions to handle parsing errors 
        //

        internal void AddErrorUnrecognizedAttribute(ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException( 
                SR.GetString(SR.Config_base_unrecognized_attribute, _reader.Name),
                this); 
 
            SchemaErrors.AddError(ex, action);
        } 

        internal void AddErrorRequiredAttribute(string attrib, ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_missing_required_attribute, attrib, _reader.Name), 
                this);
 
            SchemaErrors.AddError(ex, action); 
        }
 
        internal void AddErrorReservedAttribute(ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_reserved_attribute, _reader.Name),
                this); 

            SchemaErrors.AddError(ex, action); 
        } 

        internal void AddErrorUnrecognizedElement(ExceptionAction action) { 
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_base_unrecognized_element),
                this);
 
            SchemaErrors.AddError(ex, action);
        } 
 
        internal void VerifyAndGetNonEmptyStringAttribute(ExceptionAction action, out string newValue) {
            if (!String.IsNullOrEmpty(_reader.Value)) { 
                newValue = _reader.Value;
            }
            else {
                newValue = null; 

                ConfigurationException ex = new ConfigurationErrorsException( 
                    SR.GetString(SR.Empty_attribute, _reader.Name), 
                    this);
 
                SchemaErrors.AddError(ex, action);
            }
        }
 
        // VerifyAndGetBooleanAttribute
        // 
        // Verify and Retrieve the Boolean Attribute.  If it is not 
        // a valid value then log an error and set the value to a given default.
        // 
        internal void VerifyAndGetBooleanAttribute(
                ExceptionAction action, bool defaultValue, out bool newValue) {

            if (_reader.Value == "true") { 
                newValue = true;
            } 
            else if (_reader.Value == "false") { 
                newValue = false;
            } 
            else {
                // Unrecognized value
                newValue = defaultValue;
 
                ConfigurationErrorsException ex = new ConfigurationErrorsException(
                    SR.GetString(SR.Config_invalid_boolean_attribute, _reader.Name), 
                    this); 

                SchemaErrors.AddError(ex, action); 
            }
        }

        // 
        // Copy an XML element, then continue copying until we've hit the next element
        // or exited this depth. 
        // 
        internal bool CopyOuterXmlToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            CopyElement(utilWriter); 

            // Copy until reaching the next element, or if limitDepth == true until we've exited this depth.
            return CopyReaderToNextElement(utilWriter, limitDepth);
        } 

        // 
        // Copy an XML element but skip all its child elements, then continue copying until we've hit the next element. 
        //
        internal bool SkipChildElementsAndCopyOuterXmlToNextElement(XmlUtilWriter utilWriter) { 
            bool    isEmptyElement = _reader.IsEmptyElement;
            int     startingLine = _reader.LineNumber;
#if DBG
            int     depth = _reader.Depth; 
#endif
 
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == XmlNodeType.Element"); 

            CopyXmlNode(utilWriter); 

            // See if we need to skip any child element
            if (!isEmptyElement) {
                while (_reader.NodeType != XmlNodeType.EndElement) { 

                    // Skip all the inner child elements 
                    if (_reader.NodeType == XmlNodeType.Element) { 
                        _reader.Skip();
 
                        // We need to skip all the whitespaces following a skipped element.
                        // - If the whitespaces don't contain /r/n, then it's okay to skip them
                        //   as part of the element.
                        // - If the whitespaces contain /r/n, not skipping them will result 
                        //   in a redundant emtpy line being copied.
                        if (_reader.NodeType == XmlNodeType.Whitespace) { 
                            _reader.Skip(); 
                        }
                    } 
                    else {
                        // We want to preserve other content, e.g. comments.
                        CopyXmlNode(utilWriter);
                    } 
                }
 
                if (_reader.LineNumber != startingLine) { 
                    // The whitespace in front of the EndElement was skipped above.
                    // We need to append spaces to compensate for that. 
                    utilWriter.AppendSpacesToLinePosition(TrueLinePosition);
                }

 
#if DBG
                Debug.Assert(_reader.Depth == depth, "We should be at the same depth as the opening Element"); 
#endif 

                // Copy the end element. 
                CopyXmlNode(utilWriter);
            }

            return CopyReaderToNextElement(utilWriter, true); 
        }
 
        // 
        // Copy the reader until we hit an element, or we've exited the current depth.
        // 
        internal bool CopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            bool moreToRead = true;

            // Set the depth if we limit copying to this depth 
            int depth;
            if (limitDepth) { 
                // there is nothing in the element 
                if (_reader.NodeType == XmlNodeType.EndElement)
                    return true; 

                depth = _reader.Depth;
            }
            else { 
                depth = 0;
            } 
 
            // Copy nodes until we've reached the desired depth, or until we hit an element.
            do { 
                if (_reader.NodeType == XmlNodeType.Element)
                    break;

                if (_reader.Depth < depth) { 
                    break;
                } 
 
                moreToRead = CopyXmlNode(utilWriter);
            } while (moreToRead); 

            return moreToRead;
        }
 
        //
        // Skip over the current element and copy until the next element. 
        // This function removes the one blank line that would otherwise 
        // be inserted by simply skipping and copying to the next element
        // in a situation like this: 
        //
        //      
        //      
        //           
        //          
        //       
        //       
        //      
        // 
        internal bool SkipAndCopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == XmlNodeType.Element");

            // If the last line before the element is not blank, then we do not have to 
            // remove the blank line.
            if (!utilWriter.IsLastLineBlank) { 
                _reader.Skip(); 
                return CopyReaderToNextElement(utilWriter, limitDepth);
            } 

            // Set the depth if we limit copying to this depth
            int depth;
            if (limitDepth) { 
                depth = _reader.Depth;
            } 
            else { 
                depth = 0;
            } 

            // Skip over the element
            _reader.Skip();
 
            int lineNumberOfEndElement = _reader.LineNumber;
 
            // Read until we hit a a non-whitespace node or reach the end 
            while (!_reader.EOF) {
                if (_reader.NodeType != XmlNodeType.Whitespace) { 
                    //
                    // If the next non-whitepace node is on another line,
                    // seek back to the beginning of the current blank line,
                    // skip a blank line of whitespace, and copy the remaining whitespace. 
                    //
                    if (_reader.LineNumber > lineNumberOfEndElement) { 
                        utilWriter.SeekToLineStart(); 
                        utilWriter.AppendWhiteSpace(lineNumberOfEndElement + 1, 1, LineNumber, TrueLinePosition);
                    } 

                    break;
                }
 
                _reader.Read();
            } 
 
            // Copy nodes until we've reached the desired depth, or until we hit an element.
            while (!_reader.EOF) { 
                if (_reader.NodeType == XmlNodeType.Element)
                    break;

                if (_reader.Depth < depth) { 
                    break;
                } 
 
                CopyXmlNode(utilWriter);
            }; 

            return !_reader.EOF;
        }
 
        //
        // Copy an XML element and its children, up to and including the end element. 
        // 
        private void CopyElement(XmlUtilWriter utilWriter) {
            Debug.Assert(_reader.NodeType== XmlNodeType.Element, "_reader.NodeType== XmlNodeType.Element"); 

            int depth = _reader.Depth;
            bool isEmptyElement = _reader.IsEmptyElement;
 
            // Copy current node
            CopyXmlNode(utilWriter); 
 
            // Copy nodes while the depth is greater than the current depth.
            while (_reader.Depth > depth) { 
                CopyXmlNode(utilWriter);
            }

            // Copy the end element. 
            if (!isEmptyElement) {
                CopyXmlNode(utilWriter); 
            } 
        }
 
        //
        // Copy a single XML node, attempting to preserve whitespace.
        // A side effect of this method is to advance the reader to the next node.
        // 
        // PERFORMANCE NOTE: this function is used at runtime to copy a configuration section,
        // and at designtime to copy an entire XML document. 
        // 
        // At designtime, this function needs to be able to copy a "
            // the XmlReader API does not give us the location of the closing string, e.g. ">".
            // To correctly determine the location of the closing part, we advance the reader, 
            // determine the position of the next node, then work backwards to add whitespace
            // and add the closing string. 
            // 
            string close = null;
            int lineNumber = -1; 
            int linePosition = -1;

            int readerLineNumber = 0;
            int readerLinePosition = 0; 
            int writerLineNumber = 0;
            int writerLinePosition = 0; 
            if (utilWriter.TrackPosition) { 
                readerLineNumber = _reader.LineNumber;
                readerLinePosition = _reader.LinePosition; 
                writerLineNumber = utilWriter.LineNumber;
                writerLinePosition = utilWriter.LinePosition;
            }
 
            // We test the node type in the likely order of decreasing occurrence.
            XmlNodeType nodeType = _reader.NodeType; 
            if (nodeType == XmlNodeType.Whitespace) { 
                utilWriter.Write(_reader.Value);
            } 
            else if (nodeType == XmlNodeType.Element) {
                close = (_reader.IsEmptyElement) ? "/>" : ">";

                // get the line position after the element declaration: 
                //      
                //
                // is reported with the same position as
                // 
                //          
                // 
                // The first example has no spaces around '=', the second example does. 
                //
                while (_reader.MoveToNextAttribute()) { 
                    // get line position of the attribute declaration
                    //      
                //               ^ 
                //               linePosition
                //
                lineNumber = _reader.LineNumber;
                linePosition = _reader.LinePosition + _reader.Name.Length; 

                utilWriter.Write(""; 

                // get line position after the xml declaration: 
                //      
                // 
                // is reported with the same position as 
                //
                //           
                //
                // The first example has no spaces around '=', the second example does.
                //
                while (_reader.MoveToNextAttribute()) { 
                    // get line position of the attribute declaration
                    //      
                //
                // is reported with the same position as
                // 
                //          
                // 
                // The first example has one space between 'pi' and "value", the second has multiple spaces. 
                //
                utilWriter.AppendProcessingInstruction(_reader.Name, _reader.Value); 
            }
            else if (nodeType == XmlNodeType.EntityReference) {
                utilWriter.AppendEntityRef(_reader.Name);
            } 
            else if (nodeType == XmlNodeType.CDATA) {
                utilWriter.AppendCData(_reader.Value); 
            } 
            else if (nodeType == XmlNodeType.DocumentType) {
                // 
                // XmlNodeType.DocumentType has the following format:
                //
                //      
                // 
                // The reader only gives us the position of 'rootElementName', so we must track what was
                // written before " 
                //                            ^
                //                            linePosition 
                lineNumber = _reader.LineNumber;
                linePosition = _reader.LinePosition + _reader.Name.Length;

                // Note that there is no way to get the spacing after PUBLIC or SYSTEM attributes and their values 
                if (_reader.MoveToFirstAttribute()) {
                    // Write the space before SYSTEM or PUBLIC 
                    utilWriter.AppendRequiredWhiteSpace(lineNumber, linePosition, _reader.LineNumber, _reader.LinePosition); 

                    // Write SYSTEM or PUBLIC and the 1st value of the attribute 
                    string attrName = _reader.Name;
                    utilWriter.Write(attrName);
                    utilWriter.AppendSpace();
                    utilWriter.AppendAttributeValue(_reader); 
                    _reader.MoveToAttribute(0);
 
                    // If PUBLIC, write the second value of the attribute 
                    if (attrName == "PUBLIC") {
                        _reader.MoveToAttribute(1); 
                        utilWriter.AppendSpace();
                        utilWriter.AppendAttributeValue(_reader);
                        _reader.MoveToAttribute(1);
                    } 
                }
 
                // If there is a dtd, write it 
                if (dtdValue != null && dtdValue.Length > 0) {
                    utilWriter.Write(" ["); 
                    utilWriter.Write(dtdValue);
                    utilWriter.Write(']');
                }
 
                utilWriter.Write('>');
            } 
 
            // Advance the _reader so we can get the position of the next node.
            bool moreToRead = _reader.Read(); 
            nodeType = _reader.NodeType;

            // Close the node we are copying.
            if (close != null) { 
                //
                // Find the position of the close string, for example: 
                // 
                //            
                //                        ^ 
                //                        closeLinePosition
                //
                int startOffset = GetPositionOffset(nodeType);
                int closeLineNumber = _reader.LineNumber; 
                int closeLinePosition = _reader.LinePosition - startOffset - close.Length;
 
                // Add whitespace up to the position of the close string 
                utilWriter.AppendWhiteSpace(lineNumber, linePosition, closeLineNumber, closeLinePosition);
 
                // Write the close string
                utilWriter.Write(close);
            }
 
            //
            // Track the position of the reader based on the position of the reader 
            // before we copied this node and what we have written in copying the node. 
            // This allows us to determine the position of the "); 

            return element.ToString(); 
        }

        //
        // Copy or replace an element node. 
        // If the element is an empty element, replace it with a formatted start element if either:
        //   * The contents of the start element string need updating. 
        //   * The element needs to contain child elements. 
        //
        // If the element is empty and is replaced with a start/end element pair, return a 
        // end element string with whitespace formatting; otherwise return null.
        //
        internal string UpdateStartElement(XmlUtilWriter utilWriter, string updatedStartElement, bool needsChildren, int linePosition, int indent) {
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == NodeType.Element"); 

            string  endElement = null; 
            bool    needsEndElement = false; 
            string  elementName;
 
            elementName = _reader.Name;

            // If the element is empty, determine if a new end element is needed.
            if (_reader.IsEmptyElement) { 
                if (updatedStartElement == null && needsChildren) {
                    updatedStartElement = RetrieveFullOpenElementTag(); 
                } 

                needsEndElement = (updatedStartElement != null); 
            }

            if (updatedStartElement == null) {
                // 
                // If no changes to the start element are required, just copy it.
                // 
                CopyXmlNode(utilWriter); 
            }
            else { 
                //
                // Format a new start element/end element pair
                //
                string updatedEndElement = ""; 
                string updatedElement = updatedStartElement + updatedEndElement;
                string formattedElement = FormatXmlElement(updatedElement, linePosition, indent, true); 
 
                //
                // Get the start and end element strings from the formatted element. 
                //
                int iEndElement = formattedElement.LastIndexOf('\n') + 1;
                string startElement;
                if (needsEndElement) { 
                    endElement = formattedElement.Substring(iEndElement);
 
                    // Include a newline in the start element as we are expanding an empty element. 
                    startElement = formattedElement.Substring(0, iEndElement);
                } 
                else {
                    // Omit the newline from the start element.
                    startElement = formattedElement.Substring(0, iEndElement - 2);
                } 

                // Write the new start element. 
                utilWriter.Write(startElement); 

                // Skip over the existing start element. 
                _reader.Read();
            }

            return endElement; 
        }
 
        // 
        // Create the cached string writer if it does not exist,
        // otherwise reuse the existing buffer. 
        //
        private void ResetCachedStringWriter() {
            if (_cachedStringWriter == null) {
                _cachedStringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); 
            }
            else { 
                _cachedStringWriter.GetStringBuilder().Length = 0; 
            }
        } 

        //
        // Copy a configuration section to a string, and advance the reader.
        // 
        internal string CopySection() {
            ResetCachedStringWriter(); 
 
            // Preserve whitespace for sections for backcompat
            WhitespaceHandling originalHandling = _reader.WhitespaceHandling; 
            _reader.WhitespaceHandling = WhitespaceHandling.All;

            // Create string writer to write to
            XmlUtilWriter utilWriter = new XmlUtilWriter(_cachedStringWriter, false); 

            // Copy the element 
            CopyElement(utilWriter); 

            // Reset whitespace handling 
            _reader.WhitespaceHandling = originalHandling;

            if ((originalHandling == WhitespaceHandling.None) &&
                 (Reader.NodeType  == XmlNodeType.Whitespace))  { 
                // If we were previously suppose to skip whitespace, and now we
                // are at it, then lets jump to the next item 
                _reader.Read(); 
            }
 
            utilWriter.Flush();
            string s = ((StringWriter)utilWriter.Writer).ToString();
            return s;
        } 

        // Format an Xml element to be written to the config file. 
        // Params: 
        //   xmlElement      - the element
        //   linePosition    - start position of the element 
        //   indent          - indent for each depth
        //   skipFirstIndent - skip indent for the first element?
        //
        static internal string FormatXmlElement(string xmlElement, int linePosition, int indent, bool skipFirstIndent) { 

            XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode); 
            XmlTextReader reader = new XmlTextReader(xmlElement, XmlNodeType.Element, context); 

            StringWriter stringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); 
            XmlUtilWriter utilWriter = new XmlUtilWriter(stringWriter, false);

            // append newline before indent?
            bool newLine = false; 

            // last node visited was text? 
            bool lastWasText = false; 

            // width of line from end of indentation 
            int lineWidth;

            // length of the stringbuilder after last indent with newline
            int sbLengthLastNewLine = 0; 

            while (reader.Read()) { 
                XmlNodeType nodeType = reader.NodeType; 

                if (lastWasText) { 
                    utilWriter.Flush();
                    lineWidth = sbLengthLastNewLine - ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
                }
                else { 
                    lineWidth = 0;
                } 
 
                switch (nodeType) {
                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Element:
                    case XmlNodeType.EndElement:
                    case XmlNodeType.Comment:
                        // Do not indent if the last node was text - doing so would add whitespace 
                        // that is included as part of the text.
                        if (!skipFirstIndent && !lastWasText) { 
                            utilWriter.AppendIndent(linePosition, indent, reader.Depth, newLine); 

                            if (newLine) { 
                                utilWriter.Flush();
                                sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
                            }
                        } 
                        break;
 
                    default: 
                        break;
                } 

                lastWasText = false;
                switch (nodeType) {
                    case XmlNodeType.Whitespace: 
                        break;
 
                    case XmlNodeType.SignificantWhitespace: 
                        utilWriter.Write(reader.Value);
                        break; 

                    case XmlNodeType.CDATA:
                        utilWriter.AppendCData(reader.Value);
                        break; 

                    case XmlNodeType.ProcessingInstruction: 
                        utilWriter.AppendProcessingInstruction(reader.Name, reader.Value); 
                        break;
 
                    case XmlNodeType.Comment:
                        utilWriter.AppendComment(reader.Value);
                        break;
 
                    case XmlNodeType.Text:
                        utilWriter.AppendEscapeTextString(reader.Value); 
                        lastWasText = true; 
                        break;
 
                    case XmlNodeType.Element:
                        {
                            // Write " MAX_LINE_WIDTH) { 
                                    utilWriter.AppendIndent(linePosition, indent, reader.Depth - 1, true);
                                    lineWidth = indent; 
                                    writeSpace = false; 
                                    utilWriter.Flush();
                                    sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length; 
                                }
                                else {
                                    writeSpace = true;
                                } 

                                // Write the attribute 
                                reader.MoveToNextAttribute(); 
                                utilWriter.Flush();
                                int startLength = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length; 
                                if (writeSpace) {
                                    utilWriter.AppendSpace();
                                }
 
                                utilWriter.Write(reader.Name);
                                utilWriter.Write('='); 
                                utilWriter.AppendAttributeValue(reader); 
                                utilWriter.Flush();
                                lineWidth += ((StringWriter)utilWriter.Writer).GetStringBuilder().Length - startLength; 
                            }
                        }

                        // position reader back on element 
                        reader.MoveToElement();
 
                        // write closing tag 
                        if (reader.IsEmptyElement) {
                            utilWriter.Write(" />"); 
                        }
                        else {
                            utilWriter.Write('>');
                        } 

                        break; 
 
                    case XmlNodeType.EndElement:
                        utilWriter.Write("');
                        break;
 
                    case XmlNodeType.EntityReference:
                        utilWriter.AppendEntityRef(reader.Name); 
                        break; 

                    // Ignore 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Configuration { 
    using System.Configuration.Internal; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Collections.Generic;
    using System.Configuration;
    using System.Globalization;
    using System.IO; 
    using System.Runtime.InteropServices;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Text;
    using System.Xml; 
    using System.Net;

    //
    // XmlTextReader Helper class. 
    //
    // Provides the following services: 
    // 
    //      * Reader methods that verify restrictions on the XML that can be contained in a config file.
    //      * Methods to copy the reader stream to a writer stream. 
    //      * Method to copy a configuration section to a string.
    //      * Methods to format a string of XML.
    //
    // Errors found during read are accumlated in a ConfigurationSchemaErrors object. 
    //
    internal sealed class XmlUtil : IDisposable, IConfigErrorInfo 
    { 
        private const int   MAX_LINE_WIDTH=60;
 
        // Offset from where the reader reports the LinePosition of an Xml Node to
        // the start of that representation in text.
        static readonly int[] s_positionOffset = {
            0,      // None, 
            1,      // Element,                 
            -1,     // EndEntity,               N/A
            2,      // XmlDeclaration            0, "trueLinePosition > 0");
                return trueLinePosition; 
            }
        } 
 
        internal XmlTextReader Reader {
            get { return _reader; } 
        }

        internal ConfigurationSchemaErrors SchemaErrors {
            get { return _schemaErrors; } 
        }
 
        // 
        // Read until the Next Element element, or we hit
        // the end of the file. 
        //
        internal void ReadToNextElement() {
            while (_reader.Read()) {
                if (_reader.MoveToContent() == XmlNodeType.Element) { 
                    // We found an element, so return
                    return; 
                } 
            }
 
            // We must of hit end of file
        }

        // 
        // Skip this element and its children, then read to next start element,
        // or until we hit end of file. 
        // 
        internal void SkipToNextElement() {
            _reader.Skip(); 
            _reader.MoveToContent();

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.Element) {
                _reader.Read(); 
                _reader.MoveToContent();
            } 
        } 

        // 
        // Read to the next start element, and verify that all XML nodes read are permissible.
        //
        internal void StrictReadToNextElement(ExceptionAction action) {
            while (_reader.Read()) { 
                // optimize for the common case
                if (_reader.NodeType == XmlNodeType.Element) { 
                    return; 
                }
 
                VerifyIgnorableNodeType(action);
            }
        }
 
        //
        // Skip this element and its children, then read to next start element, 
        // or until we hit end of file. Verify that nodes that are read after the 
        // skipped element are permissible.
        // 
        internal void StrictSkipToNextElement(ExceptionAction action) {
            _reader.Skip();

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.Element) { 
                VerifyIgnorableNodeType(action);
                _reader.Read(); 
            } 
        }
 
        //
        // StrictSkipToOurParentsEndElement
        //
        // Skip until we hit the end element for our parent, and verify 
        // that nodes at the parent level are permissible.
        // 
        internal void StrictSkipToOurParentsEndElement(ExceptionAction action) { 
            int currentDepth = _reader.Depth;
 
            // Skip everything at out current level
            while (_reader.Depth >= currentDepth) {
                _reader.Skip();
            } 

            while (!_reader.EOF && _reader.NodeType != XmlNodeType.EndElement) { 
                VerifyIgnorableNodeType(action); 
                _reader.Read();
            } 
        }

        //
        // Add an error if the node type is not permitted by the configuration schema. 
        //
        internal void VerifyIgnorableNodeType(ExceptionAction action) { 
            XmlNodeType nodeType = _reader.NodeType; 

            if (nodeType != XmlNodeType.Comment && nodeType != XmlNodeType.EndElement) { 
                ConfigurationException ex = new ConfigurationErrorsException(
                    SR.GetString(SR.Config_base_unrecognized_element),
                    this);
 
                SchemaErrors.AddError(ex, action);
            } 
        } 

        // 
        // Add an error if there are attributes that have not been examined,
        // and are therefore unrecognized.
        //
        internal void VerifyNoUnrecognizedAttributes(ExceptionAction action) { 
            if (_reader.MoveToNextAttribute()) {
                AddErrorUnrecognizedAttribute(action); 
            } 
        }
 
        //
        // Add an error if the retrieved attribute is null,
        // and therefore not present.
        // 
        internal bool VerifyRequiredAttribute(
                object o, string attrName, ExceptionAction action) { 
 
            if (o == null) {
                AddErrorRequiredAttribute(attrName, action); 
                return false;
            }
            else {
                return true; 
            }
        } 
 
        //
        // Functions to handle parsing errors 
        //

        internal void AddErrorUnrecognizedAttribute(ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException( 
                SR.GetString(SR.Config_base_unrecognized_attribute, _reader.Name),
                this); 
 
            SchemaErrors.AddError(ex, action);
        } 

        internal void AddErrorRequiredAttribute(string attrib, ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_missing_required_attribute, attrib, _reader.Name), 
                this);
 
            SchemaErrors.AddError(ex, action); 
        }
 
        internal void AddErrorReservedAttribute(ExceptionAction action) {
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_reserved_attribute, _reader.Name),
                this); 

            SchemaErrors.AddError(ex, action); 
        } 

        internal void AddErrorUnrecognizedElement(ExceptionAction action) { 
            ConfigurationErrorsException ex = new ConfigurationErrorsException(
                SR.GetString(SR.Config_base_unrecognized_element),
                this);
 
            SchemaErrors.AddError(ex, action);
        } 
 
        internal void VerifyAndGetNonEmptyStringAttribute(ExceptionAction action, out string newValue) {
            if (!String.IsNullOrEmpty(_reader.Value)) { 
                newValue = _reader.Value;
            }
            else {
                newValue = null; 

                ConfigurationException ex = new ConfigurationErrorsException( 
                    SR.GetString(SR.Empty_attribute, _reader.Name), 
                    this);
 
                SchemaErrors.AddError(ex, action);
            }
        }
 
        // VerifyAndGetBooleanAttribute
        // 
        // Verify and Retrieve the Boolean Attribute.  If it is not 
        // a valid value then log an error and set the value to a given default.
        // 
        internal void VerifyAndGetBooleanAttribute(
                ExceptionAction action, bool defaultValue, out bool newValue) {

            if (_reader.Value == "true") { 
                newValue = true;
            } 
            else if (_reader.Value == "false") { 
                newValue = false;
            } 
            else {
                // Unrecognized value
                newValue = defaultValue;
 
                ConfigurationErrorsException ex = new ConfigurationErrorsException(
                    SR.GetString(SR.Config_invalid_boolean_attribute, _reader.Name), 
                    this); 

                SchemaErrors.AddError(ex, action); 
            }
        }

        // 
        // Copy an XML element, then continue copying until we've hit the next element
        // or exited this depth. 
        // 
        internal bool CopyOuterXmlToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            CopyElement(utilWriter); 

            // Copy until reaching the next element, or if limitDepth == true until we've exited this depth.
            return CopyReaderToNextElement(utilWriter, limitDepth);
        } 

        // 
        // Copy an XML element but skip all its child elements, then continue copying until we've hit the next element. 
        //
        internal bool SkipChildElementsAndCopyOuterXmlToNextElement(XmlUtilWriter utilWriter) { 
            bool    isEmptyElement = _reader.IsEmptyElement;
            int     startingLine = _reader.LineNumber;
#if DBG
            int     depth = _reader.Depth; 
#endif
 
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == XmlNodeType.Element"); 

            CopyXmlNode(utilWriter); 

            // See if we need to skip any child element
            if (!isEmptyElement) {
                while (_reader.NodeType != XmlNodeType.EndElement) { 

                    // Skip all the inner child elements 
                    if (_reader.NodeType == XmlNodeType.Element) { 
                        _reader.Skip();
 
                        // We need to skip all the whitespaces following a skipped element.
                        // - If the whitespaces don't contain /r/n, then it's okay to skip them
                        //   as part of the element.
                        // - If the whitespaces contain /r/n, not skipping them will result 
                        //   in a redundant emtpy line being copied.
                        if (_reader.NodeType == XmlNodeType.Whitespace) { 
                            _reader.Skip(); 
                        }
                    } 
                    else {
                        // We want to preserve other content, e.g. comments.
                        CopyXmlNode(utilWriter);
                    } 
                }
 
                if (_reader.LineNumber != startingLine) { 
                    // The whitespace in front of the EndElement was skipped above.
                    // We need to append spaces to compensate for that. 
                    utilWriter.AppendSpacesToLinePosition(TrueLinePosition);
                }

 
#if DBG
                Debug.Assert(_reader.Depth == depth, "We should be at the same depth as the opening Element"); 
#endif 

                // Copy the end element. 
                CopyXmlNode(utilWriter);
            }

            return CopyReaderToNextElement(utilWriter, true); 
        }
 
        // 
        // Copy the reader until we hit an element, or we've exited the current depth.
        // 
        internal bool CopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            bool moreToRead = true;

            // Set the depth if we limit copying to this depth 
            int depth;
            if (limitDepth) { 
                // there is nothing in the element 
                if (_reader.NodeType == XmlNodeType.EndElement)
                    return true; 

                depth = _reader.Depth;
            }
            else { 
                depth = 0;
            } 
 
            // Copy nodes until we've reached the desired depth, or until we hit an element.
            do { 
                if (_reader.NodeType == XmlNodeType.Element)
                    break;

                if (_reader.Depth < depth) { 
                    break;
                } 
 
                moreToRead = CopyXmlNode(utilWriter);
            } while (moreToRead); 

            return moreToRead;
        }
 
        //
        // Skip over the current element and copy until the next element. 
        // This function removes the one blank line that would otherwise 
        // be inserted by simply skipping and copying to the next element
        // in a situation like this: 
        //
        //      
        //      
        //           
        //          
        //       
        //       
        //      
        // 
        internal bool SkipAndCopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth) {
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == XmlNodeType.Element");

            // If the last line before the element is not blank, then we do not have to 
            // remove the blank line.
            if (!utilWriter.IsLastLineBlank) { 
                _reader.Skip(); 
                return CopyReaderToNextElement(utilWriter, limitDepth);
            } 

            // Set the depth if we limit copying to this depth
            int depth;
            if (limitDepth) { 
                depth = _reader.Depth;
            } 
            else { 
                depth = 0;
            } 

            // Skip over the element
            _reader.Skip();
 
            int lineNumberOfEndElement = _reader.LineNumber;
 
            // Read until we hit a a non-whitespace node or reach the end 
            while (!_reader.EOF) {
                if (_reader.NodeType != XmlNodeType.Whitespace) { 
                    //
                    // If the next non-whitepace node is on another line,
                    // seek back to the beginning of the current blank line,
                    // skip a blank line of whitespace, and copy the remaining whitespace. 
                    //
                    if (_reader.LineNumber > lineNumberOfEndElement) { 
                        utilWriter.SeekToLineStart(); 
                        utilWriter.AppendWhiteSpace(lineNumberOfEndElement + 1, 1, LineNumber, TrueLinePosition);
                    } 

                    break;
                }
 
                _reader.Read();
            } 
 
            // Copy nodes until we've reached the desired depth, or until we hit an element.
            while (!_reader.EOF) { 
                if (_reader.NodeType == XmlNodeType.Element)
                    break;

                if (_reader.Depth < depth) { 
                    break;
                } 
 
                CopyXmlNode(utilWriter);
            }; 

            return !_reader.EOF;
        }
 
        //
        // Copy an XML element and its children, up to and including the end element. 
        // 
        private void CopyElement(XmlUtilWriter utilWriter) {
            Debug.Assert(_reader.NodeType== XmlNodeType.Element, "_reader.NodeType== XmlNodeType.Element"); 

            int depth = _reader.Depth;
            bool isEmptyElement = _reader.IsEmptyElement;
 
            // Copy current node
            CopyXmlNode(utilWriter); 
 
            // Copy nodes while the depth is greater than the current depth.
            while (_reader.Depth > depth) { 
                CopyXmlNode(utilWriter);
            }

            // Copy the end element. 
            if (!isEmptyElement) {
                CopyXmlNode(utilWriter); 
            } 
        }
 
        //
        // Copy a single XML node, attempting to preserve whitespace.
        // A side effect of this method is to advance the reader to the next node.
        // 
        // PERFORMANCE NOTE: this function is used at runtime to copy a configuration section,
        // and at designtime to copy an entire XML document. 
        // 
        // At designtime, this function needs to be able to copy a "
            // the XmlReader API does not give us the location of the closing string, e.g. ">".
            // To correctly determine the location of the closing part, we advance the reader, 
            // determine the position of the next node, then work backwards to add whitespace
            // and add the closing string. 
            // 
            string close = null;
            int lineNumber = -1; 
            int linePosition = -1;

            int readerLineNumber = 0;
            int readerLinePosition = 0; 
            int writerLineNumber = 0;
            int writerLinePosition = 0; 
            if (utilWriter.TrackPosition) { 
                readerLineNumber = _reader.LineNumber;
                readerLinePosition = _reader.LinePosition; 
                writerLineNumber = utilWriter.LineNumber;
                writerLinePosition = utilWriter.LinePosition;
            }
 
            // We test the node type in the likely order of decreasing occurrence.
            XmlNodeType nodeType = _reader.NodeType; 
            if (nodeType == XmlNodeType.Whitespace) { 
                utilWriter.Write(_reader.Value);
            } 
            else if (nodeType == XmlNodeType.Element) {
                close = (_reader.IsEmptyElement) ? "/>" : ">";

                // get the line position after the element declaration: 
                //      
                //
                // is reported with the same position as
                // 
                //          
                // 
                // The first example has no spaces around '=', the second example does. 
                //
                while (_reader.MoveToNextAttribute()) { 
                    // get line position of the attribute declaration
                    //      
                //               ^ 
                //               linePosition
                //
                lineNumber = _reader.LineNumber;
                linePosition = _reader.LinePosition + _reader.Name.Length; 

                utilWriter.Write(""; 

                // get line position after the xml declaration: 
                //      
                // 
                // is reported with the same position as 
                //
                //           
                //
                // The first example has no spaces around '=', the second example does.
                //
                while (_reader.MoveToNextAttribute()) { 
                    // get line position of the attribute declaration
                    //      
                //
                // is reported with the same position as
                // 
                //          
                // 
                // The first example has one space between 'pi' and "value", the second has multiple spaces. 
                //
                utilWriter.AppendProcessingInstruction(_reader.Name, _reader.Value); 
            }
            else if (nodeType == XmlNodeType.EntityReference) {
                utilWriter.AppendEntityRef(_reader.Name);
            } 
            else if (nodeType == XmlNodeType.CDATA) {
                utilWriter.AppendCData(_reader.Value); 
            } 
            else if (nodeType == XmlNodeType.DocumentType) {
                // 
                // XmlNodeType.DocumentType has the following format:
                //
                //      
                // 
                // The reader only gives us the position of 'rootElementName', so we must track what was
                // written before " 
                //                            ^
                //                            linePosition 
                lineNumber = _reader.LineNumber;
                linePosition = _reader.LinePosition + _reader.Name.Length;

                // Note that there is no way to get the spacing after PUBLIC or SYSTEM attributes and their values 
                if (_reader.MoveToFirstAttribute()) {
                    // Write the space before SYSTEM or PUBLIC 
                    utilWriter.AppendRequiredWhiteSpace(lineNumber, linePosition, _reader.LineNumber, _reader.LinePosition); 

                    // Write SYSTEM or PUBLIC and the 1st value of the attribute 
                    string attrName = _reader.Name;
                    utilWriter.Write(attrName);
                    utilWriter.AppendSpace();
                    utilWriter.AppendAttributeValue(_reader); 
                    _reader.MoveToAttribute(0);
 
                    // If PUBLIC, write the second value of the attribute 
                    if (attrName == "PUBLIC") {
                        _reader.MoveToAttribute(1); 
                        utilWriter.AppendSpace();
                        utilWriter.AppendAttributeValue(_reader);
                        _reader.MoveToAttribute(1);
                    } 
                }
 
                // If there is a dtd, write it 
                if (dtdValue != null && dtdValue.Length > 0) {
                    utilWriter.Write(" ["); 
                    utilWriter.Write(dtdValue);
                    utilWriter.Write(']');
                }
 
                utilWriter.Write('>');
            } 
 
            // Advance the _reader so we can get the position of the next node.
            bool moreToRead = _reader.Read(); 
            nodeType = _reader.NodeType;

            // Close the node we are copying.
            if (close != null) { 
                //
                // Find the position of the close string, for example: 
                // 
                //            
                //                        ^ 
                //                        closeLinePosition
                //
                int startOffset = GetPositionOffset(nodeType);
                int closeLineNumber = _reader.LineNumber; 
                int closeLinePosition = _reader.LinePosition - startOffset - close.Length;
 
                // Add whitespace up to the position of the close string 
                utilWriter.AppendWhiteSpace(lineNumber, linePosition, closeLineNumber, closeLinePosition);
 
                // Write the close string
                utilWriter.Write(close);
            }
 
            //
            // Track the position of the reader based on the position of the reader 
            // before we copied this node and what we have written in copying the node. 
            // This allows us to determine the position of the "); 

            return element.ToString(); 
        }

        //
        // Copy or replace an element node. 
        // If the element is an empty element, replace it with a formatted start element if either:
        //   * The contents of the start element string need updating. 
        //   * The element needs to contain child elements. 
        //
        // If the element is empty and is replaced with a start/end element pair, return a 
        // end element string with whitespace formatting; otherwise return null.
        //
        internal string UpdateStartElement(XmlUtilWriter utilWriter, string updatedStartElement, bool needsChildren, int linePosition, int indent) {
            Debug.Assert(_reader.NodeType == XmlNodeType.Element, "_reader.NodeType == NodeType.Element"); 

            string  endElement = null; 
            bool    needsEndElement = false; 
            string  elementName;
 
            elementName = _reader.Name;

            // If the element is empty, determine if a new end element is needed.
            if (_reader.IsEmptyElement) { 
                if (updatedStartElement == null && needsChildren) {
                    updatedStartElement = RetrieveFullOpenElementTag(); 
                } 

                needsEndElement = (updatedStartElement != null); 
            }

            if (updatedStartElement == null) {
                // 
                // If no changes to the start element are required, just copy it.
                // 
                CopyXmlNode(utilWriter); 
            }
            else { 
                //
                // Format a new start element/end element pair
                //
                string updatedEndElement = ""; 
                string updatedElement = updatedStartElement + updatedEndElement;
                string formattedElement = FormatXmlElement(updatedElement, linePosition, indent, true); 
 
                //
                // Get the start and end element strings from the formatted element. 
                //
                int iEndElement = formattedElement.LastIndexOf('\n') + 1;
                string startElement;
                if (needsEndElement) { 
                    endElement = formattedElement.Substring(iEndElement);
 
                    // Include a newline in the start element as we are expanding an empty element. 
                    startElement = formattedElement.Substring(0, iEndElement);
                } 
                else {
                    // Omit the newline from the start element.
                    startElement = formattedElement.Substring(0, iEndElement - 2);
                } 

                // Write the new start element. 
                utilWriter.Write(startElement); 

                // Skip over the existing start element. 
                _reader.Read();
            }

            return endElement; 
        }
 
        // 
        // Create the cached string writer if it does not exist,
        // otherwise reuse the existing buffer. 
        //
        private void ResetCachedStringWriter() {
            if (_cachedStringWriter == null) {
                _cachedStringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); 
            }
            else { 
                _cachedStringWriter.GetStringBuilder().Length = 0; 
            }
        } 

        //
        // Copy a configuration section to a string, and advance the reader.
        // 
        internal string CopySection() {
            ResetCachedStringWriter(); 
 
            // Preserve whitespace for sections for backcompat
            WhitespaceHandling originalHandling = _reader.WhitespaceHandling; 
            _reader.WhitespaceHandling = WhitespaceHandling.All;

            // Create string writer to write to
            XmlUtilWriter utilWriter = new XmlUtilWriter(_cachedStringWriter, false); 

            // Copy the element 
            CopyElement(utilWriter); 

            // Reset whitespace handling 
            _reader.WhitespaceHandling = originalHandling;

            if ((originalHandling == WhitespaceHandling.None) &&
                 (Reader.NodeType  == XmlNodeType.Whitespace))  { 
                // If we were previously suppose to skip whitespace, and now we
                // are at it, then lets jump to the next item 
                _reader.Read(); 
            }
 
            utilWriter.Flush();
            string s = ((StringWriter)utilWriter.Writer).ToString();
            return s;
        } 

        // Format an Xml element to be written to the config file. 
        // Params: 
        //   xmlElement      - the element
        //   linePosition    - start position of the element 
        //   indent          - indent for each depth
        //   skipFirstIndent - skip indent for the first element?
        //
        static internal string FormatXmlElement(string xmlElement, int linePosition, int indent, bool skipFirstIndent) { 

            XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode); 
            XmlTextReader reader = new XmlTextReader(xmlElement, XmlNodeType.Element, context); 

            StringWriter stringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture); 
            XmlUtilWriter utilWriter = new XmlUtilWriter(stringWriter, false);

            // append newline before indent?
            bool newLine = false; 

            // last node visited was text? 
            bool lastWasText = false; 

            // width of line from end of indentation 
            int lineWidth;

            // length of the stringbuilder after last indent with newline
            int sbLengthLastNewLine = 0; 

            while (reader.Read()) { 
                XmlNodeType nodeType = reader.NodeType; 

                if (lastWasText) { 
                    utilWriter.Flush();
                    lineWidth = sbLengthLastNewLine - ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
                }
                else { 
                    lineWidth = 0;
                } 
 
                switch (nodeType) {
                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Element:
                    case XmlNodeType.EndElement:
                    case XmlNodeType.Comment:
                        // Do not indent if the last node was text - doing so would add whitespace 
                        // that is included as part of the text.
                        if (!skipFirstIndent && !lastWasText) { 
                            utilWriter.AppendIndent(linePosition, indent, reader.Depth, newLine); 

                            if (newLine) { 
                                utilWriter.Flush();
                                sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
                            }
                        } 
                        break;
 
                    default: 
                        break;
                } 

                lastWasText = false;
                switch (nodeType) {
                    case XmlNodeType.Whitespace: 
                        break;
 
                    case XmlNodeType.SignificantWhitespace: 
                        utilWriter.Write(reader.Value);
                        break; 

                    case XmlNodeType.CDATA:
                        utilWriter.AppendCData(reader.Value);
                        break; 

                    case XmlNodeType.ProcessingInstruction: 
                        utilWriter.AppendProcessingInstruction(reader.Name, reader.Value); 
                        break;
 
                    case XmlNodeType.Comment:
                        utilWriter.AppendComment(reader.Value);
                        break;
 
                    case XmlNodeType.Text:
                        utilWriter.AppendEscapeTextString(reader.Value); 
                        lastWasText = true; 
                        break;
 
                    case XmlNodeType.Element:
                        {
                            // Write " MAX_LINE_WIDTH) { 
                                    utilWriter.AppendIndent(linePosition, indent, reader.Depth - 1, true);
                                    lineWidth = indent; 
                                    writeSpace = false; 
                                    utilWriter.Flush();
                                    sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length; 
                                }
                                else {
                                    writeSpace = true;
                                } 

                                // Write the attribute 
                                reader.MoveToNextAttribute(); 
                                utilWriter.Flush();
                                int startLength = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length; 
                                if (writeSpace) {
                                    utilWriter.AppendSpace();
                                }
 
                                utilWriter.Write(reader.Name);
                                utilWriter.Write('='); 
                                utilWriter.AppendAttributeValue(reader); 
                                utilWriter.Flush();
                                lineWidth += ((StringWriter)utilWriter.Writer).GetStringBuilder().Length - startLength; 
                            }
                        }

                        // position reader back on element 
                        reader.MoveToElement();
 
                        // write closing tag 
                        if (reader.IsEmptyElement) {
                            utilWriter.Write(" />"); 
                        }
                        else {
                            utilWriter.Write('>');
                        } 

                        break; 
 
                    case XmlNodeType.EndElement:
                        utilWriter.Write("');
                        break;
 
                    case XmlNodeType.EntityReference:
                        utilWriter.AppendEntityRef(reader.Name); 
                        break; 

                    // Ignore 

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK