XmlQueryOutput.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 / XmlUtils / System / Xml / Xsl / Runtime / XmlQueryOutput.cs / 1 / XmlQueryOutput.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
using System.Collections; 
using System.ComponentModel; 
using System.Diagnostics;
using System.Globalization; 
using System.Xml;
using System.Xml.XPath;

namespace System.Xml.Xsl.Runtime { 
    using Res = System.Xml.Utils.Res;
 
    internal enum XmlState { 
        WithinSequence = 0,     // Adding items to a top-level sequence
        EnumAttrs,              // Adding attributes to an element 
        WithinContent,          // Adding content to an element
        WithinAttr,             // Adding text to an attribute
        WithinNmsp,             // Adding text to an namespace
        WithinComment,          // Adding text to a comment 
        WithinPI,               // Adding text to a processing instruction
    }; 
 

    ///  
    /// At run-time, a number of checks may need to be made in order to generate the correct sequence of calls
    /// to XmlRawWriter:
    ///   1. Well-formedness: Illegal state transitions, StartContent detection, no-content element detection
    ///   2. Cached attributes: In XSLT, attributes override previously constructed attributes with the same name, 
    ///      meaning that attribute names and values cannot be prematurely sent to XmlRawWriter.
    ///   3. Cached namespaces: All namespaces are tracked in order to ensure adequate namespaces and to ensure 
    ///      minimal (or something close) namespaces. 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    public sealed class XmlQueryOutput : XmlWriter {
        // Never set these fields directly--instead use corresponding properties
        private XmlRawWriter xwrt;                  // Output to XmlRawWriter--get and set this using the Writer property
 
        // It is OK to set these properties directly
        private XmlQueryRuntime runtime;            // The XmlQueryRuntime instance that keeps global state 
        private XmlAttributeCache attrCache;        // Cache used to detect duplicate attributes 
        private int depth;                          // Depth of the currently constructing tree
        private XmlState xstate;                    // Current XML state 
        private XmlSequenceWriter seqwrt;           // Current XmlSequenceWriter
        private XmlNamespaceManager nsmgr;          // Output namespace manager
        private int cntNmsp;                        // Number of pending namespaces
        private Hashtable conflictPrefixes;         // Remembers prefixes that were auto-generated previously in case they can be reused 
        private int prefixIndex;                    // Counter used to auto-generate non-conflicting attribute prefixes
        private string piTarget/*nmspPrefix*/;      // Cache pi target or namespace prefix 
        private StringConcat nodeText;              // Cache pi, comment, or namespace text 
        private Stack stkNames;                     // Keep stack of name parts computed during StartElement
        private XPathNodeType rootType;             // NodeType of the root of the tree 
        private bool useDefNmsp;                    // True if xmlns="" is either locally declared or used by element name

        /// 
        /// This constructor is internal so that external users cannot construct it (and therefore we do not have to test it separately). 
        /// Initialize output state to accept top-level sequences.
        ///  
        internal XmlQueryOutput(XmlQueryRuntime runtime, XmlSequenceWriter seqwrt) { 
            this.runtime = runtime;
            this.seqwrt = seqwrt; 
            this.xstate = XmlState.WithinSequence;
        }

        ///  
        /// This constructor is internal so that external users cannot construct it (and therefore we do not have to test it separately).
        /// Initialize output state to accept Rtf content (top-level sequences are therefore prohibited). 
        ///  
        internal XmlQueryOutput(XmlQueryRuntime runtime, XmlEventCache xwrt) {
            this.runtime = runtime; 
            this.xwrt = xwrt;
            this.xstate = XmlState.WithinContent;
            this.depth = 1;
            this.rootType = XPathNodeType.Root; 
        }
 
        ///  
        /// Sequence writer to which output is directed by this class.
        ///  
        internal XmlSequenceWriter SequenceWriter {
            get { return this.seqwrt; }
        }
 
        /// 
        /// Raw writer to which output is directed by this class. 
        ///  
        internal XmlRawWriter Writer {
            get { return this.xwrt; } 
            set {
                // If new writer might remove itself from pipeline, have it callback on this method when it's ready to go
                IRemovableWriter removable = value as IRemovableWriter;
                if (removable != null) 
                    removable.OnRemoveWriterEvent = SetWrappedWriter;
 
                this.xwrt = value; 
            }
        } 

        /// 
        /// This method will be called if "xwrt" is a writer which no longer needs to be part of the pipeline and
        /// wishes to replace itself with a different writer.  For example, the auto-detect writer replaces itself 
        /// with the Html or Xml writer once it has determined which output mode to use.
        ///  
        private void SetWrappedWriter(XmlRawWriter writer) { 
            // Reuse XmlAttributeCache so that it doesn't have to be recreated every time
            if (Writer is XmlAttributeCache) 
                this.attrCache = (XmlAttributeCache) Writer;

            Writer = writer;
        } 

 
        //----------------------------------------------- 
        // XmlWriter methods
        //----------------------------------------------- 

        /// 
        /// Should never be called.
        ///  
        public override void WriteStartDocument() {
            throw new NotSupportedException(); 
        } 

        ///  
        /// Should never be called.
        /// 
        public override void WriteStartDocument(bool standalone) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Should never be called.
        ///  
        public override void WriteEndDocument() {
            throw new NotSupportedException();
        }
 
        /// 
        /// Should never be called. 
        ///  
        public override void WriteDocType(string name, string pubid, string sysid, string subset) {
            throw new NotSupportedException(); 
        }

        /// 
        /// Before calling XmlRawWriter.WriteStartElement(), perform various checks to ensure well-formedness. 
        /// 
        public override void WriteStartElement(string prefix, string localName, string ns) { 
            Debug.Assert(prefix != null && localName != null && localName.Length != 0 && ns != null, "Invalid argument"); 
            Debug.Assert(ValidateNames.ValidateName(prefix, localName, ns, XPathNodeType.Element, ValidateNames.Flags.All), "Name validation failed");
 
            // Xml state transitions
            ConstructWithinContent(XPathNodeType.Element);

            // Call XmlRawWriter.WriteStartElement 
            WriteStartElementUnchecked(prefix, localName, ns);
 
            // Ensure that element's namespace declaration is declared 
            WriteNamespaceDeclarationUnchecked(prefix, ns);
 
            // Cache attributes in order to detect duplicates
            if (this.attrCache == null)
                this.attrCache = new XmlAttributeCache();
 
            this.attrCache.Init(Writer);
            Writer = this.attrCache; 
            this.attrCache = null; 

            // Push element names onto a stack 
            PushElementNames(prefix, localName, ns);
        }

        ///  
        /// Before calling XmlRawWriter.WriteEndElement(), perform various checks to ensure well-formedness.
        ///  
        public override void WriteEndElement() { 
            string prefix, localName, ns;
 
            // Determine whether element had no content
            if (this.xstate == XmlState.EnumAttrs) {
                // No content, so call StartElementContent now
                StartElementContentUnchecked(); 
            }
 
            // Call XmlRawWriter.WriteEndElement 
            PopElementNames(out prefix, out localName, out ns);
            WriteEndElementUnchecked(prefix, localName, ns); 

            // Xml state transitions
            if (this.depth == 0)
                EndTree(); 
        }
 
        ///  
        /// Same as calling WriteEndElement().
        ///  
        public override void WriteFullEndElement() {
            WriteEndElement();
        }
 
        /// 
        /// Before calling XmlRawWriter.WriteStartAttribute(), perform various checks to ensure well-formedness. 
        ///  
        public override void WriteStartAttribute(string prefix, string localName, string ns) {
            Debug.Assert(prefix != null && localName != null && ns != null, "Invalid argument"); 

            if (prefix.Length == 5 && prefix == "xmlns") {
                // Handle namespace attributes that are not sent directly to WriteNamespaceDeclaration
                WriteStartNamespace(localName); 
            }
            else { 
                // All other attributes 
                Debug.Assert(ValidateNames.ValidateName(prefix, localName, ns, XPathNodeType.Attribute, ValidateNames.Flags.All));
 
                // Xml state transitions
                ConstructInEnumAttrs(XPathNodeType.Attribute);

                // Check for prefix conflicts and possibly declare prefix 
                if (ns.Length != 0 && this.depth != 0)
                    prefix = CheckAttributePrefix(prefix, ns); 
 
                // Output the attribute
                WriteStartAttributeUnchecked(prefix, localName, ns); 
            }
        }

        ///  
        /// Before calling XmlRawWriter.WriteEndAttribute(), perform various checks to ensure well-formedness.
        ///  
        public override void WriteEndAttribute() { 
            if (this.xstate == XmlState.WithinNmsp) {
                WriteEndNamespace(); 
            }
            else {
                WriteEndAttributeUnchecked();
 
                if (this.depth == 0)
                    EndTree(); 
            } 
        }
 
        /// 
        /// Before writing a comment, perform various checks to ensure well-formedness.
        /// 
        public override void WriteComment(string text) { 
            WriteStartComment();
            WriteCommentString(text); 
            WriteEndComment(); 
        }
 
        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness.
        /// 
        public override void WriteProcessingInstruction(string target, string text) { 
            WriteStartProcessingInstruction(target);
            WriteProcessingInstructionString(text); 
            WriteEndProcessingInstruction(); 
        }
 
        /// 
        /// Should never be called.
        /// 
        public override void WriteEntityRef(string name) { 
            throw new NotSupportedException();
        } 
 
        /// 
        /// Should never be called. 
        /// 
        public override void WriteCharEntity(char ch) {
            throw new NotSupportedException();
        } 

        ///  
        /// Should never be called. 
        /// 
        public override void WriteSurrogateCharEntity(char lowChar, char highChar) { 
            throw new NotSupportedException();
        }

        ///  
        /// Treat whitespace as regular text.
        ///  
        public override void WriteWhitespace(string ws) { 
            throw new NotSupportedException();
        } 

        /// 
        /// Before writing text, perform various checks to ensure well-formedness.
        ///  
        public override void WriteString(string text) {
            WriteString(text, false); 
        } 

        ///  
        /// Before writing text, perform various checks to ensure well-formedness.
        /// 
        public override void WriteChars(char[] buffer, int index, int count) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Write text, but do not escape special characters.
        ///  
        public override void WriteRaw(char[] buffer, int index, int count) {
            throw new NotSupportedException();
        }
 
        /// 
        /// Write text, but do not escape special characters. 
        ///  
        public override void WriteRaw(string data) {
            WriteString(data, true); 
        }

        /// 
        /// Write CData text as regular text. 
        /// 
        public override void WriteCData(string text) { 
            WriteString(text, false); 
        }
 
        /// 
        /// Should never be called.
        /// 
        public override void WriteBase64(byte[] buffer, int index, int count) { 
            throw new NotSupportedException();
        } 
 
        /// 
        /// Should never be called. 
        /// 
        public override WriteState WriteState {
            get { throw new NotSupportedException(); }
        } 

        ///  
        /// No-op. 
        /// 
        public override void Close() { 
        }

        /// 
        /// No-op. 
        /// 
        public override void Flush() { 
        } 

        ///  
        /// Should never be called.
        /// 
        public override string LookupPrefix(string ns) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Should never be called.
        ///  
        public override XmlSpace XmlSpace {
            get { throw new NotSupportedException(); }
        }
 
        /// 
        /// Should never be called. 
        ///  
        public override string XmlLang {
            get { throw new NotSupportedException(); } 
        }


        //----------------------------------------------- 
        // XmlQueryOutput methods (XmlSequenceWriter)
        //----------------------------------------------- 
 
        /// 
        /// Call XmlSequenceWriter.StartTree() in order to start construction of a new tree. 
        /// 
        public void StartTree(XPathNodeType rootType) {
            Debug.Assert(this.xstate == XmlState.WithinSequence, "StartTree cannot be called in the " + this.xstate + " state.");
            Writer = this.seqwrt.StartTree(rootType, this.nsmgr, this.runtime.NameTable); 
            this.rootType = rootType;
            this.xstate = (rootType == XPathNodeType.Attribute || rootType == XPathNodeType.Namespace) ? XmlState.EnumAttrs : XmlState.WithinContent; 
        } 

        ///  
        /// Call XmlSequenceWriter.EndTree().
        /// 
        public void EndTree() {
            Debug.Assert(this.xstate == XmlState.EnumAttrs || this.xstate == XmlState.WithinContent, "EndTree cannot be called in the " + this.xstate + " state."); 
            this.seqwrt.EndTree();
            this.xstate = XmlState.WithinSequence; 
            Writer = null; 
        }
 

        //-----------------------------------------------
        // XmlQueryOutput methods (XmlRawWriter)
        //----------------------------------------------- 

        ///  
        /// Call XmlRawWriter.WriteStartElement() with prefix, local-name, ns, and schema type. 
        /// 
        public void WriteStartElementUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.WithinContent, "WriteStartElement cannot be called in the " + this.xstate + " state.");
            if (this.nsmgr != null) this.nsmgr.PushScope();
            Writer.WriteStartElement(prefix, localName, ns);
            this.xstate = XmlState.EnumAttrs; 
            this.depth++;
            this.useDefNmsp = ns.Length == 0; 
        } 

        ///  
        /// Call XmlRawWriter.WriteStartElement() with empty prefix, ns, and null schema type.
        /// 
        public void WriteStartElementUnchecked(string localName) {
            WriteStartElementUnchecked(string.Empty, localName, string.Empty); 
        }
 
        ///  
        /// Call XmlRawWriter.StartElementContent().
        ///  
        public void StartElementContentUnchecked() {
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "StartElementContent cannot be called in the " + this.xstate + " state.");

            // Output any cached namespaces 
            if (this.cntNmsp != 0)
                WriteCachedNamespaces(); 
 
            Writer.StartElementContent();
            this.xstate = XmlState.WithinContent; 
            this.useDefNmsp = false;
        }

        ///  
        /// Call XmlRawWriter.WriteEndElement() with prefix, local-name, and ns.
        ///  
        public void WriteEndElementUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.EnumAttrs || this.xstate == XmlState.WithinContent, "WriteEndElement cannot be called in the " + this.xstate + " state.");
            Writer.WriteEndElement(prefix, localName, ns); 
            this.xstate = XmlState.WithinContent;
            this.depth--;
            if (this.nsmgr != null) this.nsmgr.PopScope();
        } 

        ///  
        /// Call XmlRawWriter.WriteEndElement() with empty prefix, ns. 
        /// 
        public void WriteEndElementUnchecked(string localName) { 
            WriteEndElementUnchecked(string.Empty, localName, string.Empty);
        }

        ///  
        /// XmlRawWriter.WriteStartAttribute() with prefix, local-name, ns, and schema type.
        ///  
        public void WriteStartAttributeUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "WriteStartAttribute cannot be called in the " + this.xstate + " state.");
            Writer.WriteStartAttribute(prefix, localName, ns); 
            this.xstate = XmlState.WithinAttr;
            this.depth++;
        }
 
        /// 
        /// XmlRawWriter.WriteStartAttribute() with empty prefix, ns, and null schema type. 
        ///  
        public void WriteStartAttributeUnchecked(string localName) {
            WriteStartAttributeUnchecked(string.Empty, localName, string.Empty); 
        }

        /// 
        /// XmlRawWriter.WriteEndAttribute(). 
        /// 
        public void WriteEndAttributeUnchecked() { 
            Debug.Assert(this.xstate == XmlState.WithinAttr, "WriteEndAttribute cannot be called in the " + this.xstate + " state."); 
            Writer.WriteEndAttribute();
            this.xstate = XmlState.EnumAttrs; 
            this.depth--;
        }

        ///  
        /// Add a new namespace declaration -- xmlns:prefix="ns" -- to the set of in-scope declarations.
        /// NOTE: This method should only be called if caller can guarantee that the current state is EnumAttrs 
        ///       and that there will be no namespace conflicts in the current scope (e.g. trying to map the 
        ///       same prefix to different namespaces within the same element start tag).  If no such
        ///       guarantees exist, then WriteNamespaceDeclaration() should be called instead. 
        /// 
        public void WriteNamespaceDeclarationUnchecked(string prefix, string ns) {
            Debug.Assert(prefix != null && ns != null);
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "WriteNamespaceDeclaration cannot be called in the " + this.xstate + " state."); 

            // xmlns:foo="" is illegal 
            Debug.Assert(prefix.Length == 0 || ns.Length != 0); 

            if (this.depth == 0) { 
                // At top-level, so write namespace declaration directly to output
                Writer.WriteNamespaceDeclaration(prefix, ns);
                return;
            } 

            if (this.nsmgr == null) { 
                // If namespace manager has no namespaces, then xmlns="" is in scope by default 
                if (ns.Length == 0 && prefix.Length == 0)
                    return; 

                this.nsmgr = new XmlNamespaceManager(this.runtime.NameTable);
                this.nsmgr.PushScope();
            } 

            if (this.nsmgr.LookupNamespace(prefix) != ns) 
                AddNamespace(prefix, ns); 
        }
 
        /// 
        /// Write a text block to the XmlRawWriter.
        /// 
        public void WriteStringUnchecked(string text) { 
            Debug.Assert(this.xstate != XmlState.WithinSequence && this.xstate != XmlState.EnumAttrs, "WriteTextBlock cannot be called in the " + this.xstate + " state.");
            Writer.WriteString(text); 
        } 

        ///  
        /// Write a text block without escaping special characters.
        /// 
        public void WriteRawUnchecked(string text) {
            Debug.Assert(this.xstate != XmlState.WithinSequence && this.xstate != XmlState.EnumAttrs, "WriteTextBlockNoEntities cannot be called in the " + this.xstate + " state."); 
            Writer.WriteRaw(text);
        } 
 

        //----------------------------------------------- 
        // XmlQueryOutput methods
        //-----------------------------------------------

        ///  
        /// Before calling XmlSequenceWriter.StartTree(), perform checks to ensure well-formedness.
        ///  
        public void WriteStartRoot() { 
            Debug.Assert(this.depth == 0, "Root node can only be constructed at top-level.");
            if (this.xstate != XmlState.WithinSequence) 
                ThrowInvalidStateError(XPathNodeType.Root);

            StartTree(XPathNodeType.Root);
            this.depth++; 
        }
 
        ///  
        /// Call XmlSequenceWriter.EndTree() and reset state.
        ///  
        public void WriteEndRoot() {
            Debug.Assert(this.depth == 1, "Root node can only be constructed at top-level.");
            this.depth--;
            EndTree(); 
        }
 
        ///  
        /// WriteStartElement() with empty prefix, ns.
        ///  
        public void WriteStartElementLocalName(string localName) {
            WriteStartElement(string.Empty, localName, string.Empty);
        }
 
        /// 
        /// WriteStartAttribute() with empty prefix, ns, and null schema type. 
        ///  
        public void WriteStartAttributeLocalName(string localName) {
            WriteStartAttribute(string.Empty, localName, string.Empty); 
        }

        /// 
        /// Write an element with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings. 
        /// 
        public void WriteStartElementComputed(string tagName, int prefixMappingsIndex) { 
            WriteStartComputed(XPathNodeType.Element, tagName, prefixMappingsIndex); 
        }
 
        /// 
        /// Write an element with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        /// 
        public void WriteStartElementComputed(string tagName, string ns) { 
            WriteStartComputed(XPathNodeType.Element, tagName, ns);
        } 
 
        /// 
        /// Write an element with a name that is copied from the navigator. 
        /// 
        public void WriteStartElementComputed(XPathNavigator navigator) {
            WriteStartComputed(XPathNodeType.Element, navigator);
        } 

        ///  
        /// Write an element with a name that is derived from the XmlQualifiedName. 
        /// 
        public void WriteStartElementComputed(XmlQualifiedName name) { 
            WriteStartComputed(XPathNodeType.Element, name);
        }

        ///  
        /// Write an attribute with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings.
        ///  
        public void WriteStartAttributeComputed(string tagName, int prefixMappingsIndex) { 
            WriteStartComputed(XPathNodeType.Attribute, tagName, prefixMappingsIndex);
        } 

        /// 
        /// Write an attribute with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        ///  
        public void WriteStartAttributeComputed(string tagName, string ns) {
            WriteStartComputed(XPathNodeType.Attribute, tagName, ns); 
        } 

        ///  
        /// Write an attribute with a name that is copied from the navigator.
        /// 
        public void WriteStartAttributeComputed(XPathNavigator navigator) {
            WriteStartComputed(XPathNodeType.Attribute, navigator); 
        }
 
        ///  
        /// Write an attribute with a name that is derived from the XmlQualifiedName.
        ///  
        public void WriteStartAttributeComputed(XmlQualifiedName name) {
            WriteStartComputed(XPathNodeType.Attribute, name);
        }
 
        /// 
        /// Before calling XmlRawWriter.WriteNamespaceDeclaration(), perform various checks to ensure well-formedness. 
        ///  
        public void WriteNamespaceDeclaration(string prefix, string ns) {
            string nsExisting; 
            Debug.Assert(prefix != null && ns != null);

            ConstructInEnumAttrs(XPathNodeType.Namespace);
 
            if (this.nsmgr == null) {
                // If namespace manager has not yet been created, then there is no possibility of conflict 
                WriteNamespaceDeclarationUnchecked(prefix, ns); 
            }
            else { 
                nsExisting = this.nsmgr.LookupNamespace(prefix);
                if (ns != nsExisting) {
                    // prefix = "", ns = "", nsExisting --> Look for xmlns="", found xmlns="foo"
                    // prefix = "", ns, nsExisting = null --> Look for xmlns="uri", no uri found 
                    // prefix = "", ns, nsExisting = "" --> Look for xmlns="uri", found xmlns=""
                    // prefix = "", ns, nsExisting --> Look for xmlns="uri", found xmlns="uri2" 
                    // prefix, ns, nsExisting = null --> Look for xmlns:foo="uri", no uri found 
                    // prefix, ns, nsExisting --> Look for xmlns:foo="uri", found xmlns:foo="uri2"
 
                    // If the prefix is mapped to a uri,
                    if (nsExisting != null) {
                        // Then throw an error except in a special case involving default namespace declaration
                        // Looking for xmlns="", found xmlns="foo" -- ERROR 
                        // Looking for xmlns="uri", found xmlns="uri2" -- ERROR
                        // Looking for xmlns="uri", found xmlns="" -- OK, unless xmlns="" declaration is 
                        //                                            local or element's namespace is "" 
                        if (prefix.Length != 0 || nsExisting.Length != 0 || this.useDefNmsp)
                            throw new XslTransformException(Res.XmlIl_NmspConflict, new string[] {prefix.Length == 0 ? "" : ":", prefix, ns, nsExisting}); 
                    }

                    // Add namespace to manager and write it to output
                    AddNamespace(prefix, ns); 
                }
            } 
 
            if (this.depth == 0)
                EndTree(); 
        }

        /// 
        /// Before writing a namespace, perform various checks to ensure well-formedness. 
        /// 
        public void WriteStartNamespace(string prefix) { 
            Debug.Assert(prefix != null, "Invalid argument"); 

            // Handle namespace attributes that are not sent directly to WriteNamespaceDeclaration 
            ConstructInEnumAttrs(XPathNodeType.Namespace);
            this.piTarget/*nmspPrefix*/ = prefix;
            this.nodeText.Clear();
 
            this.xstate = XmlState.WithinNmsp;
            this.depth++; 
        } 

        ///  
        /// Cache the namespace's text.
        /// 
        public void WriteNamespaceString(string text) {
            Debug.Assert(this.xstate == XmlState.WithinNmsp, "WriteNamespaceString cannot be called in the " + this.xstate + " state."); 
            this.nodeText.ConcatNoDelimiter(text);
        } 
 
        /// 
        /// Before writing a namespace, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndNamespace() {
            Debug.Assert(this.xstate == XmlState.WithinNmsp, "WriteEndNamespace cannot be called in the " + this.xstate + " state.");
 
            this.xstate = XmlState.EnumAttrs;
            this.depth--; 
 
            // Write cached namespace attribute
            WriteNamespaceDeclaration(this.piTarget/*nmspPrefix*/, this.nodeText.GetResult()); 

            if (this.depth == 0)
                EndTree();
        } 

        ///  
        /// Before writing a comment, perform various checks to ensure well-formedness. 
        /// 
        public void WriteStartComment() { 
            // Xml state transitions
            ConstructWithinContent(XPathNodeType.Comment);

            this.nodeText.Clear(); 
            this.xstate = XmlState.WithinComment;
            this.depth++; 
        } 

        ///  
        /// Cache the comment's text.
        /// 
        public void WriteCommentString(string text) {
            Debug.Assert(this.xstate == XmlState.WithinComment, "WriteCommentString cannot be called in the " + this.xstate + " state."); 
            this.nodeText.ConcatNoDelimiter(text);
        } 
 
        /// 
        /// Before writing a comment, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndComment() {
            Debug.Assert(this.xstate == XmlState.WithinComment, "WriteEndComment cannot be called in the " + this.xstate + " state.");
 
            Writer.WriteComment(this.nodeText.GetResult());
 
            this.xstate = XmlState.WithinContent; 
            this.depth--;
 
            if (this.depth == 0)
                EndTree();
        }
 
        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness. 
        ///  
        public void WriteStartProcessingInstruction(string target) {
            // Xml state transitions 
            ConstructWithinContent(XPathNodeType.ProcessingInstruction);

            // Verify PI name
            ValidateNames.ValidateNameThrow("", target, "", XPathNodeType.ProcessingInstruction, ValidateNames.Flags.AllExceptPrefixMapping); 

            this.piTarget = target; 
            this.nodeText.Clear(); 

            this.xstate = XmlState.WithinPI; 
            this.depth++;
        }

        ///  
        /// Cache the processing instruction's text.
        ///  
        public void WriteProcessingInstructionString(string text) { 
            Debug.Assert(this.xstate == XmlState.WithinPI, "WriteProcessingInstructionString cannot be called in the " + this.xstate + " state.");
            this.nodeText.ConcatNoDelimiter(text); 
        }

        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndProcessingInstruction() { 
            Debug.Assert(this.xstate == XmlState.WithinPI, "WriteEndProcessingInstruction cannot be called in the " + this.xstate + " state."); 

            Writer.WriteProcessingInstruction(this.piTarget, this.nodeText.GetResult()); 

            this.xstate = XmlState.WithinContent;
            this.depth--;
 
            // Xml state transitions
            if (this.depth == 0) 
                EndTree(); 
        }
 
        /// 
        /// Write an item to output.  If currently constructing an Xml tree, then the item is always copied.
        /// At the top-level, the item's identity is preserved unless it's an atomic value.
        ///  
        public void WriteItem(XPathItem item) {
            if (item.IsNode) { 
                XPathNavigator navigator = (XPathNavigator) item; 

                // If this is a top-level node, write a reference to it; else copy it by value 
                if (this.xstate == XmlState.WithinSequence)
                    this.seqwrt.WriteItem(navigator);
                else
                    CopyNode(navigator); 
            }
            else { 
                // Call WriteItem for atomic values 
                Debug.Assert(this.xstate == XmlState.WithinSequence, "Values can only be written at the top-level.");
                this.seqwrt.WriteItem(item); 
            }
        }

        ///  
        /// Copy a node by value to output according to Xslt rules:
        ///   1. Identity is never preserved 
        ///   2. If the item is an Rtf, preserve serialization hints when copying. 
        ///   3. If the item is a Root node, copy the children of the Root
        ///  
        public void XsltCopyOf(XPathNavigator navigator) {
            RtfNavigator navRtf = navigator as RtfNavigator;

            if (navRtf != null) { 
                // Copy Rtf
                navRtf.CopyToWriter(this); 
            } 
            else if (navigator.NodeType == XPathNodeType.Root) {
                // Copy children of root 
                if (navigator.MoveToFirstChild()) {
                    do {
                        CopyNode(navigator);
                    } 
                    while (navigator.MoveToNext());
 
                    navigator.MoveToParent(); 
                }
            } 
            else {
                // Copy node
                CopyNode(navigator);
            } 
        }
 
        ///  
        /// Begin shallow copy of the navigator's current node to output.  Returns true if EndCopy
        /// should be called to complete the copy operation. 
        /// Automatically copies all in-scope namespaces on elements.
        /// 
        public bool StartCopy(XPathNavigator navigator) {
            // StartDocument is a no-op 
            if (navigator.NodeType == XPathNodeType.Root)
                return true; 
 
            if (StartCopy(navigator, true)) {
                Debug.Assert(navigator.NodeType == XPathNodeType.Element, "StartCopy should return true only for Element nodes."); 

                // Copy namespaces to output
                CopyNamespaces(navigator, XPathNamespaceScope.ExcludeXml);
 
                return true;
            } 
 
            return false;
        } 

        /// 
        /// End shallow copy of the navigator's current node.  Should be called only for Element and Document nodes.
        ///  
        public void EndCopy(XPathNavigator navigator) {
            if (navigator.NodeType == XPathNodeType.Element) 
                WriteEndElement(); 
            else
                Debug.Assert(navigator.NodeType == XPathNodeType.Root, "EndCopy should only be called for Element and Document nodes."); 
        }


        //----------------------------------------------- 
        // Helper methods
        //----------------------------------------------- 
 
        /// 
        /// Add an in-scope namespace. 
        /// 
        private void AddNamespace(string prefix, string ns) {
            this.nsmgr.AddNamespace(prefix, ns);
            this.cntNmsp++; 
            if (ns.Length == 0)
                this.useDefNmsp = true; 
        } 

        ///  
        /// Before writing text, perform various checks to ensure well-formedness.
        /// 
        private void WriteString(string text, bool disableOutputEscaping) {
            Debug.Assert(text != null, "Invalid argument"); 

            // Xml state transitions 
            switch (this.xstate) { 
                case XmlState.WithinSequence:
                    // Start constructing new tree 
                    StartTree(XPathNodeType.Text);
                    goto case XmlState.WithinContent;

                case XmlState.WithinContent: 
                    if (disableOutputEscaping)
                        WriteRawUnchecked(text); 
                    else 
                        WriteStringUnchecked(text);
                    break; 

                case XmlState.EnumAttrs:
                    // Enumerating attributes, so write text as element content
                    StartElementContentUnchecked(); 
                    goto case XmlState.WithinContent;
 
                case XmlState.WithinAttr: 
                    WriteStringUnchecked(text);
                    break; 

                case XmlState.WithinNmsp:
                    WriteNamespaceString(text);
                    break; 

                case XmlState.WithinComment: 
                    // Comment text 
                    WriteCommentString(text);
                    break; 

                case XmlState.WithinPI:
                    // PI text
                    WriteProcessingInstructionString(text); 
                    break;
 
                default: 
                    Debug.Assert(false, "Text cannot be output in the " + this.xstate + " state.");
                    break; 
            }

            if (this.depth == 0)
                EndTree(); 
        }
 
        ///  
        /// Deep copy the subtree that is rooted at this navigator's current position to output.  If the current
        /// item is an element, copy all in-scope namespace nodes. 
        /// 
        private void CopyNode(XPathNavigator navigator) {
            XPathNodeType nodeType;
            int depthStart = this.depth; 
            Debug.Assert(navigator != null);
 
            while (true) { 
                if (StartCopy(navigator, this.depth == depthStart)) {
                    nodeType = navigator.NodeType; 
                    Debug.Assert(nodeType == XPathNodeType.Element, "StartCopy should return true only for Element nodes.");

                    // Copy attributes
                    if (navigator.MoveToFirstAttribute()) { 
                        do {
                            StartCopy(navigator, false); 
                        } 
                        while (navigator.MoveToNextAttribute());
                        navigator.MoveToParent(); 
                    }

                    // Copy namespaces in document order (navigator returns them in reverse document order)
                    CopyNamespaces(navigator, (this.depth - 1 == depthStart) ? XPathNamespaceScope.ExcludeXml : XPathNamespaceScope.Local); 

                    StartElementContentUnchecked(); 
 
                    // If children exist, move down to next level
                    if (navigator.MoveToFirstChild()) 
                        continue;

                    EndCopy(navigator, (this.depth - 1) == depthStart);
                } 

                // No children 
                while (true) { 
                    if (this.depth == depthStart) {
                        // The entire subtree has been copied 
                        return;
                    }

                    if (navigator.MoveToNext()) { 
                        // Found a sibling, so break to outer loop
                        break; 
                    } 

                    // No siblings, so move up to previous level 
                    navigator.MoveToParent();

                    EndCopy(navigator, (this.depth - 1) == depthStart);
                } 
            }
        } 
 
        /// 
        /// Begin shallow copy of the navigator's current node to output.  Returns true if EndCopy 
        /// should be called to complete the copy operation.
        /// 
        private bool StartCopy(XPathNavigator navigator, bool callChk) {
            bool mayHaveChildren = false; 

            switch (navigator.NodeType) { 
                case XPathNodeType.Element: 
                    // If checks need to be made, call XmlQueryOutput.WriteStartElement
                    if (callChk) { 
                        WriteStartElement(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI);
                    }
                    else {
                        WriteStartElementUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
 
                    mayHaveChildren = true; 
                    break;
 
                case XPathNodeType.Attribute:
                    // If checks need to be made, call XmlQueryOutput.WriteStartAttribute
                    if (callChk) {
                        WriteStartAttribute(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
                    else { 
                        WriteStartAttributeUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
 
                    // Write attribute text
                    WriteString(navigator.Value);

                    // If checks need to be made, call XmlQueryOutput.WriteEndAttribute 
                    if (callChk) {
                        WriteEndAttribute(); 
                    } 
                    else {
                        WriteEndAttributeUnchecked(); 
                    }
                    break;

                case XPathNodeType.Namespace: 
                    // If checks need to be made, call XmlQueryOutput.WriteNamespaceDeclaration
                    if (callChk) { 
                        // Do not allow namespaces to be copied after attributes 
                        XmlAttributeCache attrCache = Writer as XmlAttributeCache;
                        if (attrCache != null && attrCache.Count != 0) 
                            throw new XslTransformException(Res.XmlIl_NmspAfterAttr, string.Empty);

                        WriteNamespaceDeclaration(navigator.LocalName, navigator.Value);
                    } 
                    else {
                        WriteNamespaceDeclarationUnchecked(navigator.LocalName, navigator.Value); 
                    } 
                    break;
 
                case XPathNodeType.Text:
                case XPathNodeType.SignificantWhitespace:
                case XPathNodeType.Whitespace:
                    // If checks need to be made, call XmlQueryOutput.WriteString 
                    if (callChk) {
                        WriteString(navigator.Value, false); 
                    } 
                    else {
                        // No flags are set, so this is simple element text (attributes, comments, pi's copy own text) 
                        WriteStringUnchecked(navigator.Value);
                    }
                    break;
 
                case XPathNodeType.Root:
                    // Document node is invalid except at the top-level 
                    Debug.Assert(this.xstate != XmlState.WithinSequence, "StartCopy should not called if state is WithinSequence"); 
                    ThrowInvalidStateError(XPathNodeType.Root);
                    break; 

                case XPathNodeType.Comment:
                    WriteStartComment();
                    WriteCommentString(navigator.Value); 
                    WriteEndComment();
                    break; 
 
                case XPathNodeType.ProcessingInstruction:
                    WriteStartProcessingInstruction(navigator.LocalName); 
                    WriteProcessingInstructionString(navigator.Value);
                    WriteEndProcessingInstruction();
                    break;
 
                default:
                    Debug.Assert(false); 
                    break; 
            }
 
            return mayHaveChildren;
        }

        ///  
        /// End shallow copy of the navigator's current node to output.  This method should only be called if StartCopy
        /// returned true. 
        ///  
        private void EndCopy(XPathNavigator navigator, bool callChk) {
            Debug.Assert(navigator.NodeType == XPathNodeType.Element); 
            Debug.Assert(this.xstate == XmlState.WithinContent, "EndCopy cannot be called in the " + this.xstate + " state.");

            if (callChk)
                WriteEndElement(); 
            else
                WriteEndElementUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
        } 

        ///  
        /// Copy all namespaces of the specified type (in-scope, exclude-xml, local) in document order to output.
        /// 
        private void CopyNamespaces(XPathNavigator navigator, XPathNamespaceScope nsScope) {
            Debug.Assert(navigator.NodeType == XPathNodeType.Element, "Only elements have namespaces to copy"); 

            // Default namespace undeclaration isn't included in navigator's namespace list, so add it now 
            if (navigator.NamespaceURI.Length == 0) { 
                Debug.Assert(navigator.LocalName.Length != 0, "xmlns:foo='' isn't allowed");
                WriteNamespaceDeclarationUnchecked(string.Empty, string.Empty); 
            }

            // Since the namespace list is arranged in reverse-document order, recursively reverse it.
            if (navigator.MoveToFirstNamespace(nsScope)) { 
                CopyNamespacesHelper(navigator, nsScope);
                navigator.MoveToParent(); 
            } 
        }
 
        /// 
        /// Recursive helper function that reverses order of the namespaces retrieved by MoveToFirstNamespace and
        /// MoveToNextNamespace.
        ///  
        private void CopyNamespacesHelper(XPathNavigator navigator, XPathNamespaceScope nsScope) {
            string prefix = navigator.LocalName; 
            string ns = navigator.Value; 

            if (navigator.MoveToNextNamespace(nsScope)) 
                CopyNamespacesHelper(navigator, nsScope);

            // No possibility for conflict, since we're copying namespaces from well-formed element
            WriteNamespaceDeclarationUnchecked(prefix, ns); 
        }
 
        ///  
        /// Ensure that state transitions to WithinContent.
        ///  
        private void ConstructWithinContent(XPathNodeType rootType) {
            Debug.Assert(rootType == XPathNodeType.Element || rootType == XPathNodeType.Comment || rootType == XPathNodeType.ProcessingInstruction);

            switch (this.xstate) { 
                case XmlState.WithinSequence:
                    // If state is WithinSequence, call XmlSequenceWriter.StartTree 
                    StartTree(rootType); 
                    this.xstate = XmlState.WithinContent;
                    break; 

                case XmlState.WithinContent:
                    // Already within element content
                    break; 

                case XmlState.EnumAttrs: 
                    // Start element content 
                    StartElementContentUnchecked();
                    break; 

                default:
                    // Construction is not allowed in this state
                    ThrowInvalidStateError(rootType); 
                    break;
            } 
        } 

        ///  
        /// Ensure that state transitions to EnumAttrs.
        /// 
        private void ConstructInEnumAttrs(XPathNodeType rootType) {
            Debug.Assert(rootType == XPathNodeType.Attribute || rootType == XPathNodeType.Namespace); 

            switch (this.xstate) { 
                case XmlState.WithinSequence: 
                    StartTree(rootType);
                    this.xstate = XmlState.EnumAttrs; 
                    break;

                case XmlState.EnumAttrs:
                    // Already in EnumAttrs state 
                    break;
 
                default: 
                    // Construction is not allowed in this state
                    ThrowInvalidStateError(rootType); 
                    break;
            }
        }
 
        /// 
        /// Namespace declarations are added to this.nsmgr.  Just before element content has begun, write out 
        /// all namespaces that were declared locally on the element. 
        /// 
        private void WriteCachedNamespaces() { 
            string prefix, ns;

            while (this.cntNmsp != 0) {
                // Output each prefix->ns mapping pair 
                Debug.Assert(this.nsmgr != null);
                this.cntNmsp--; 
                this.nsmgr.GetNamespaceDeclaration(this.cntNmsp, out prefix, out ns); 
                Writer.WriteNamespaceDeclaration(prefix, ns);
            } 
        }

        /// 
        /// Return the type of node that is under construction given the specified XmlState. 
        /// 
        private XPathNodeType XmlStateToNodeType(XmlState xstate) { 
            switch (xstate) { 
                case XmlState.EnumAttrs: return XPathNodeType.Element;
                case XmlState.WithinContent: return XPathNodeType.Element; 
                case XmlState.WithinAttr: return XPathNodeType.Attribute;
                case XmlState.WithinComment: return XPathNodeType.Comment;
                case XmlState.WithinPI: return XPathNodeType.ProcessingInstruction;
            } 

            Debug.Assert(false, xstate.ToString() + " is not a valid XmlState."); 
            return XPathNodeType.Element; 
        }
 
        /// 
        /// If attribute's prefix conflicts with other prefixes then redeclare the prefix.  If the prefix has
        /// not yet been declared, then add it to the namespace manager.
        ///  
        private string CheckAttributePrefix(string prefix, string ns) {
            string nsExisting; 
            Debug.Assert(prefix.Length != 0 && ns.Length != 0); 

            // Ensure that this attribute's prefix does not conflict with previously declared prefixes in this scope 
            if (this.nsmgr == null) {
                // If namespace manager has no namespaces, then there is no possibility of conflict
                WriteNamespaceDeclarationUnchecked(prefix, ns);
            } 
            else {
                while (true) { 
                    // If prefix is already mapped to a different namespace, 
                    nsExisting = this.nsmgr.LookupNamespace(prefix);
                    if (nsExisting != ns) { 

                        // Then if the prefix is already mapped,
                        if (nsExisting != null) {
                            // Then there is a conflict that must be resolved by finding another prefix 
                            // Always find a new prefix, even if the conflict didn't occur in the current scope
                            // This decision allows more aggressive namespace analysis at compile-time 
                            prefix = RemapPrefix(prefix, ns, false); 
                            continue;
                        } 

                        // Add the mapping to the current scope
                        AddNamespace(prefix, ns);
                    } 
                    break;
                } 
            } 

            return prefix; 
        }

        /// 
        /// Remaps an element or attribute prefix using the following rules: 
        ///
        ///   1. If another in-scope prefix is already mapped to "ns", then use that 
        ///   2. Otherwise, if a prefix was previously mapped to "ns" by this method, then use that 
        ///   3. Otherwise, generate a new prefix of the form 'xp_??', where ?? is a stringized counter
        /// 
        /// These rules tend to reduce the number of unique prefixes used throughout the tree.
        /// 
        private string RemapPrefix(string prefix, string ns, bool isElemPrefix) {
            const string PrefixFormat = "xp_{0}"; 
            string genPrefix;
            Debug.Assert(prefix != null && ns != null && ns.Length != 0); 
 
            if (this.conflictPrefixes == null)
                this.conflictPrefixes = new Hashtable(16); 

            if (this.nsmgr == null) {
                this.nsmgr = new XmlNamespaceManager(this.runtime.NameTable);
                this.nsmgr.PushScope(); 
            }
 
            // Rule #1: If another in-scope prefix is already mapped to "ns", then use that 
            genPrefix = this.nsmgr.LookupPrefix(ns);
            if (genPrefix != null) { 
                // Can't use an empty prefix for an attribute
                if (isElemPrefix || genPrefix.Length != 0)
                    goto ReturnPrefix;
            } 

            // Rule #2: Otherwise, if a prefix was previously mapped to "ns" by this method, then use that 
            // Make sure that any previous prefix is different than "prefix" 
            genPrefix = this.conflictPrefixes[ns] as string;
            if (genPrefix != null && genPrefix != prefix) { 
                // Can't use an empty prefix for an attribute
                if (isElemPrefix || genPrefix.Length != 0)
                    goto ReturnPrefix;
            } 

            // Rule #3: Otherwise, generate a new prefix of the form 'xp_??', where ?? is a stringized counter 
            genPrefix = string.Format(CultureInfo.InvariantCulture, PrefixFormat, this.prefixIndex++); 

        ReturnPrefix: 
            // Save generated prefix so that it can be possibly be reused later
            this.conflictPrefixes[ns] = genPrefix;

            return genPrefix; 
        }
 
        ///  
        /// Write an element or attribute with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, string tagName, int prefixMappingsIndex) {
            string prefix, localName, ns;

            // Parse the tag name and map the prefix to a namespace 
            runtime.ParseTagName(tagName, prefixMappingsIndex, out prefix, out localName, out ns);
 
            // Validate the name parts 
            prefix = EnsureValidName(prefix, localName, ns, nodeType);
 
            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, localName, ns);
            else
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        ///  
        /// Write an element or attribute with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, string tagName, string ns) {
            string prefix, localName;

            // Parse the tagName as a prefix, localName pair 
            ValidateNames.ParseQNameThrow(tagName, out prefix, out localName);
 
            // Validate the name parts 
            prefix = EnsureValidName(prefix, localName, ns, nodeType);
 
            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, localName, ns);
            else
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        ///  
        /// Write an element or attribute with a name that is copied from the navigator.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, XPathNavigator navigator) {
            string prefix, localName, ns;

            prefix = navigator.Prefix; 
            localName = navigator.LocalName;
            ns = navigator.NamespaceURI; 
 
            if (navigator.NodeType != nodeType) {
                // Validate the name parts 
                prefix = EnsureValidName(prefix, localName, ns, nodeType);
            }

            if (nodeType == XPathNodeType.Element) 
                WriteStartElement(prefix, localName, ns);
            else 
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        /// 
        /// Write an element or attribute with a name that is derived from the XmlQualifiedName.
        /// 
        private void WriteStartComputed(XPathNodeType nodeType, XmlQualifiedName name) { 
            string prefix;
            Debug.Assert(ValidateNames.ParseNCName(name.Name, 0) == name.Name.Length); 
 
            // Validate the name parts
            prefix = (name.Namespace.Length != 0) ? RemapPrefix(string.Empty, name.Namespace, nodeType == XPathNodeType.Element) : string.Empty; 
            prefix = EnsureValidName(prefix, name.Name, name.Namespace, nodeType);

            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, name.Name, name.Namespace); 
            else
                WriteStartAttribute(prefix, name.Name, name.Namespace); 
        } 

        ///  
        /// Ensure that the specified name parts are valid according to Xml 1.0 and Namespace 1.0 rules.  Try to remap
        /// the prefix in order to attain validity.  Throw if validity is not possible.  Otherwise, return the (possibly
        /// remapped) prefix.
        ///  
        private string EnsureValidName(string prefix, string localName, string ns, XPathNodeType nodeType) {
            if (!ValidateNames.ValidateName(prefix, localName, ns, nodeType, ValidateNames.Flags.AllExceptNCNames)) { 
                // Name parts are not valid as is.  Try to re-map the prefix. 
                prefix = (ns.Length != 0) ? RemapPrefix(string.Empty, ns, nodeType == XPathNodeType.Element) : string.Empty;
 
                // Throw if validation does not work this time
                ValidateNames.ValidateNameThrow(prefix, localName, ns, nodeType, ValidateNames.Flags.AllExceptNCNames);
            }
 
            return prefix;
        } 
 
        /// 
        /// Push element name parts onto the stack. 
        /// 
        private void PushElementNames(string prefix, string localName, string ns) {
            // Push the name parts onto a stack
            if (this.stkNames == null) 
                this.stkNames = new Stack();
 
            this.stkNames.Push(prefix); 
            this.stkNames.Push(localName);
            this.stkNames.Push(ns); 
        }

        /// 
        /// Pop element name parts from the stack. 
        /// 
        private void PopElementNames(out string prefix, out string localName, out string ns) { 
            Debug.Assert(this.stkNames != null); 

            ns = this.stkNames.Pop() as string; 
            localName = this.stkNames.Pop() as string;
            prefix = this.stkNames.Pop() as string;
        }
 
        /// 
        /// Throw an invalid state transition error. 
        ///  
        private void ThrowInvalidStateError(XPathNodeType constructorType) {
            switch (constructorType) { 
                case XPathNodeType.Element:
                case XPathNodeType.Root:
                case XPathNodeType.Text:
                case XPathNodeType.Comment: 
                case XPathNodeType.ProcessingInstruction:
                    throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {constructorType.ToString(), XmlStateToNodeType(this.xstate).ToString()}); 
 
                case XPathNodeType.Attribute:
                case XPathNodeType.Namespace: 
                    if (this.depth == 1)
                        throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {constructorType.ToString(), this.rootType.ToString()});

                    if (this.xstate == XmlState.WithinContent) 
                        throw new XslTransformException(Res.XmlIl_BadXmlStateAttr, string.Empty);
 
                    goto case XPathNodeType.Element; 

                default: 
                    throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {"Unknown", XmlStateToNodeType(this.xstate).ToString()});
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
using System.Collections; 
using System.ComponentModel; 
using System.Diagnostics;
using System.Globalization; 
using System.Xml;
using System.Xml.XPath;

namespace System.Xml.Xsl.Runtime { 
    using Res = System.Xml.Utils.Res;
 
    internal enum XmlState { 
        WithinSequence = 0,     // Adding items to a top-level sequence
        EnumAttrs,              // Adding attributes to an element 
        WithinContent,          // Adding content to an element
        WithinAttr,             // Adding text to an attribute
        WithinNmsp,             // Adding text to an namespace
        WithinComment,          // Adding text to a comment 
        WithinPI,               // Adding text to a processing instruction
    }; 
 

    ///  
    /// At run-time, a number of checks may need to be made in order to generate the correct sequence of calls
    /// to XmlRawWriter:
    ///   1. Well-formedness: Illegal state transitions, StartContent detection, no-content element detection
    ///   2. Cached attributes: In XSLT, attributes override previously constructed attributes with the same name, 
    ///      meaning that attribute names and values cannot be prematurely sent to XmlRawWriter.
    ///   3. Cached namespaces: All namespaces are tracked in order to ensure adequate namespaces and to ensure 
    ///      minimal (or something close) namespaces. 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    public sealed class XmlQueryOutput : XmlWriter {
        // Never set these fields directly--instead use corresponding properties
        private XmlRawWriter xwrt;                  // Output to XmlRawWriter--get and set this using the Writer property
 
        // It is OK to set these properties directly
        private XmlQueryRuntime runtime;            // The XmlQueryRuntime instance that keeps global state 
        private XmlAttributeCache attrCache;        // Cache used to detect duplicate attributes 
        private int depth;                          // Depth of the currently constructing tree
        private XmlState xstate;                    // Current XML state 
        private XmlSequenceWriter seqwrt;           // Current XmlSequenceWriter
        private XmlNamespaceManager nsmgr;          // Output namespace manager
        private int cntNmsp;                        // Number of pending namespaces
        private Hashtable conflictPrefixes;         // Remembers prefixes that were auto-generated previously in case they can be reused 
        private int prefixIndex;                    // Counter used to auto-generate non-conflicting attribute prefixes
        private string piTarget/*nmspPrefix*/;      // Cache pi target or namespace prefix 
        private StringConcat nodeText;              // Cache pi, comment, or namespace text 
        private Stack stkNames;                     // Keep stack of name parts computed during StartElement
        private XPathNodeType rootType;             // NodeType of the root of the tree 
        private bool useDefNmsp;                    // True if xmlns="" is either locally declared or used by element name

        /// 
        /// This constructor is internal so that external users cannot construct it (and therefore we do not have to test it separately). 
        /// Initialize output state to accept top-level sequences.
        ///  
        internal XmlQueryOutput(XmlQueryRuntime runtime, XmlSequenceWriter seqwrt) { 
            this.runtime = runtime;
            this.seqwrt = seqwrt; 
            this.xstate = XmlState.WithinSequence;
        }

        ///  
        /// This constructor is internal so that external users cannot construct it (and therefore we do not have to test it separately).
        /// Initialize output state to accept Rtf content (top-level sequences are therefore prohibited). 
        ///  
        internal XmlQueryOutput(XmlQueryRuntime runtime, XmlEventCache xwrt) {
            this.runtime = runtime; 
            this.xwrt = xwrt;
            this.xstate = XmlState.WithinContent;
            this.depth = 1;
            this.rootType = XPathNodeType.Root; 
        }
 
        ///  
        /// Sequence writer to which output is directed by this class.
        ///  
        internal XmlSequenceWriter SequenceWriter {
            get { return this.seqwrt; }
        }
 
        /// 
        /// Raw writer to which output is directed by this class. 
        ///  
        internal XmlRawWriter Writer {
            get { return this.xwrt; } 
            set {
                // If new writer might remove itself from pipeline, have it callback on this method when it's ready to go
                IRemovableWriter removable = value as IRemovableWriter;
                if (removable != null) 
                    removable.OnRemoveWriterEvent = SetWrappedWriter;
 
                this.xwrt = value; 
            }
        } 

        /// 
        /// This method will be called if "xwrt" is a writer which no longer needs to be part of the pipeline and
        /// wishes to replace itself with a different writer.  For example, the auto-detect writer replaces itself 
        /// with the Html or Xml writer once it has determined which output mode to use.
        ///  
        private void SetWrappedWriter(XmlRawWriter writer) { 
            // Reuse XmlAttributeCache so that it doesn't have to be recreated every time
            if (Writer is XmlAttributeCache) 
                this.attrCache = (XmlAttributeCache) Writer;

            Writer = writer;
        } 

 
        //----------------------------------------------- 
        // XmlWriter methods
        //----------------------------------------------- 

        /// 
        /// Should never be called.
        ///  
        public override void WriteStartDocument() {
            throw new NotSupportedException(); 
        } 

        ///  
        /// Should never be called.
        /// 
        public override void WriteStartDocument(bool standalone) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Should never be called.
        ///  
        public override void WriteEndDocument() {
            throw new NotSupportedException();
        }
 
        /// 
        /// Should never be called. 
        ///  
        public override void WriteDocType(string name, string pubid, string sysid, string subset) {
            throw new NotSupportedException(); 
        }

        /// 
        /// Before calling XmlRawWriter.WriteStartElement(), perform various checks to ensure well-formedness. 
        /// 
        public override void WriteStartElement(string prefix, string localName, string ns) { 
            Debug.Assert(prefix != null && localName != null && localName.Length != 0 && ns != null, "Invalid argument"); 
            Debug.Assert(ValidateNames.ValidateName(prefix, localName, ns, XPathNodeType.Element, ValidateNames.Flags.All), "Name validation failed");
 
            // Xml state transitions
            ConstructWithinContent(XPathNodeType.Element);

            // Call XmlRawWriter.WriteStartElement 
            WriteStartElementUnchecked(prefix, localName, ns);
 
            // Ensure that element's namespace declaration is declared 
            WriteNamespaceDeclarationUnchecked(prefix, ns);
 
            // Cache attributes in order to detect duplicates
            if (this.attrCache == null)
                this.attrCache = new XmlAttributeCache();
 
            this.attrCache.Init(Writer);
            Writer = this.attrCache; 
            this.attrCache = null; 

            // Push element names onto a stack 
            PushElementNames(prefix, localName, ns);
        }

        ///  
        /// Before calling XmlRawWriter.WriteEndElement(), perform various checks to ensure well-formedness.
        ///  
        public override void WriteEndElement() { 
            string prefix, localName, ns;
 
            // Determine whether element had no content
            if (this.xstate == XmlState.EnumAttrs) {
                // No content, so call StartElementContent now
                StartElementContentUnchecked(); 
            }
 
            // Call XmlRawWriter.WriteEndElement 
            PopElementNames(out prefix, out localName, out ns);
            WriteEndElementUnchecked(prefix, localName, ns); 

            // Xml state transitions
            if (this.depth == 0)
                EndTree(); 
        }
 
        ///  
        /// Same as calling WriteEndElement().
        ///  
        public override void WriteFullEndElement() {
            WriteEndElement();
        }
 
        /// 
        /// Before calling XmlRawWriter.WriteStartAttribute(), perform various checks to ensure well-formedness. 
        ///  
        public override void WriteStartAttribute(string prefix, string localName, string ns) {
            Debug.Assert(prefix != null && localName != null && ns != null, "Invalid argument"); 

            if (prefix.Length == 5 && prefix == "xmlns") {
                // Handle namespace attributes that are not sent directly to WriteNamespaceDeclaration
                WriteStartNamespace(localName); 
            }
            else { 
                // All other attributes 
                Debug.Assert(ValidateNames.ValidateName(prefix, localName, ns, XPathNodeType.Attribute, ValidateNames.Flags.All));
 
                // Xml state transitions
                ConstructInEnumAttrs(XPathNodeType.Attribute);

                // Check for prefix conflicts and possibly declare prefix 
                if (ns.Length != 0 && this.depth != 0)
                    prefix = CheckAttributePrefix(prefix, ns); 
 
                // Output the attribute
                WriteStartAttributeUnchecked(prefix, localName, ns); 
            }
        }

        ///  
        /// Before calling XmlRawWriter.WriteEndAttribute(), perform various checks to ensure well-formedness.
        ///  
        public override void WriteEndAttribute() { 
            if (this.xstate == XmlState.WithinNmsp) {
                WriteEndNamespace(); 
            }
            else {
                WriteEndAttributeUnchecked();
 
                if (this.depth == 0)
                    EndTree(); 
            } 
        }
 
        /// 
        /// Before writing a comment, perform various checks to ensure well-formedness.
        /// 
        public override void WriteComment(string text) { 
            WriteStartComment();
            WriteCommentString(text); 
            WriteEndComment(); 
        }
 
        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness.
        /// 
        public override void WriteProcessingInstruction(string target, string text) { 
            WriteStartProcessingInstruction(target);
            WriteProcessingInstructionString(text); 
            WriteEndProcessingInstruction(); 
        }
 
        /// 
        /// Should never be called.
        /// 
        public override void WriteEntityRef(string name) { 
            throw new NotSupportedException();
        } 
 
        /// 
        /// Should never be called. 
        /// 
        public override void WriteCharEntity(char ch) {
            throw new NotSupportedException();
        } 

        ///  
        /// Should never be called. 
        /// 
        public override void WriteSurrogateCharEntity(char lowChar, char highChar) { 
            throw new NotSupportedException();
        }

        ///  
        /// Treat whitespace as regular text.
        ///  
        public override void WriteWhitespace(string ws) { 
            throw new NotSupportedException();
        } 

        /// 
        /// Before writing text, perform various checks to ensure well-formedness.
        ///  
        public override void WriteString(string text) {
            WriteString(text, false); 
        } 

        ///  
        /// Before writing text, perform various checks to ensure well-formedness.
        /// 
        public override void WriteChars(char[] buffer, int index, int count) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Write text, but do not escape special characters.
        ///  
        public override void WriteRaw(char[] buffer, int index, int count) {
            throw new NotSupportedException();
        }
 
        /// 
        /// Write text, but do not escape special characters. 
        ///  
        public override void WriteRaw(string data) {
            WriteString(data, true); 
        }

        /// 
        /// Write CData text as regular text. 
        /// 
        public override void WriteCData(string text) { 
            WriteString(text, false); 
        }
 
        /// 
        /// Should never be called.
        /// 
        public override void WriteBase64(byte[] buffer, int index, int count) { 
            throw new NotSupportedException();
        } 
 
        /// 
        /// Should never be called. 
        /// 
        public override WriteState WriteState {
            get { throw new NotSupportedException(); }
        } 

        ///  
        /// No-op. 
        /// 
        public override void Close() { 
        }

        /// 
        /// No-op. 
        /// 
        public override void Flush() { 
        } 

        ///  
        /// Should never be called.
        /// 
        public override string LookupPrefix(string ns) {
            throw new NotSupportedException(); 
        }
 
        ///  
        /// Should never be called.
        ///  
        public override XmlSpace XmlSpace {
            get { throw new NotSupportedException(); }
        }
 
        /// 
        /// Should never be called. 
        ///  
        public override string XmlLang {
            get { throw new NotSupportedException(); } 
        }


        //----------------------------------------------- 
        // XmlQueryOutput methods (XmlSequenceWriter)
        //----------------------------------------------- 
 
        /// 
        /// Call XmlSequenceWriter.StartTree() in order to start construction of a new tree. 
        /// 
        public void StartTree(XPathNodeType rootType) {
            Debug.Assert(this.xstate == XmlState.WithinSequence, "StartTree cannot be called in the " + this.xstate + " state.");
            Writer = this.seqwrt.StartTree(rootType, this.nsmgr, this.runtime.NameTable); 
            this.rootType = rootType;
            this.xstate = (rootType == XPathNodeType.Attribute || rootType == XPathNodeType.Namespace) ? XmlState.EnumAttrs : XmlState.WithinContent; 
        } 

        ///  
        /// Call XmlSequenceWriter.EndTree().
        /// 
        public void EndTree() {
            Debug.Assert(this.xstate == XmlState.EnumAttrs || this.xstate == XmlState.WithinContent, "EndTree cannot be called in the " + this.xstate + " state."); 
            this.seqwrt.EndTree();
            this.xstate = XmlState.WithinSequence; 
            Writer = null; 
        }
 

        //-----------------------------------------------
        // XmlQueryOutput methods (XmlRawWriter)
        //----------------------------------------------- 

        ///  
        /// Call XmlRawWriter.WriteStartElement() with prefix, local-name, ns, and schema type. 
        /// 
        public void WriteStartElementUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.WithinContent, "WriteStartElement cannot be called in the " + this.xstate + " state.");
            if (this.nsmgr != null) this.nsmgr.PushScope();
            Writer.WriteStartElement(prefix, localName, ns);
            this.xstate = XmlState.EnumAttrs; 
            this.depth++;
            this.useDefNmsp = ns.Length == 0; 
        } 

        ///  
        /// Call XmlRawWriter.WriteStartElement() with empty prefix, ns, and null schema type.
        /// 
        public void WriteStartElementUnchecked(string localName) {
            WriteStartElementUnchecked(string.Empty, localName, string.Empty); 
        }
 
        ///  
        /// Call XmlRawWriter.StartElementContent().
        ///  
        public void StartElementContentUnchecked() {
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "StartElementContent cannot be called in the " + this.xstate + " state.");

            // Output any cached namespaces 
            if (this.cntNmsp != 0)
                WriteCachedNamespaces(); 
 
            Writer.StartElementContent();
            this.xstate = XmlState.WithinContent; 
            this.useDefNmsp = false;
        }

        ///  
        /// Call XmlRawWriter.WriteEndElement() with prefix, local-name, and ns.
        ///  
        public void WriteEndElementUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.EnumAttrs || this.xstate == XmlState.WithinContent, "WriteEndElement cannot be called in the " + this.xstate + " state.");
            Writer.WriteEndElement(prefix, localName, ns); 
            this.xstate = XmlState.WithinContent;
            this.depth--;
            if (this.nsmgr != null) this.nsmgr.PopScope();
        } 

        ///  
        /// Call XmlRawWriter.WriteEndElement() with empty prefix, ns. 
        /// 
        public void WriteEndElementUnchecked(string localName) { 
            WriteEndElementUnchecked(string.Empty, localName, string.Empty);
        }

        ///  
        /// XmlRawWriter.WriteStartAttribute() with prefix, local-name, ns, and schema type.
        ///  
        public void WriteStartAttributeUnchecked(string prefix, string localName, string ns) { 
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "WriteStartAttribute cannot be called in the " + this.xstate + " state.");
            Writer.WriteStartAttribute(prefix, localName, ns); 
            this.xstate = XmlState.WithinAttr;
            this.depth++;
        }
 
        /// 
        /// XmlRawWriter.WriteStartAttribute() with empty prefix, ns, and null schema type. 
        ///  
        public void WriteStartAttributeUnchecked(string localName) {
            WriteStartAttributeUnchecked(string.Empty, localName, string.Empty); 
        }

        /// 
        /// XmlRawWriter.WriteEndAttribute(). 
        /// 
        public void WriteEndAttributeUnchecked() { 
            Debug.Assert(this.xstate == XmlState.WithinAttr, "WriteEndAttribute cannot be called in the " + this.xstate + " state."); 
            Writer.WriteEndAttribute();
            this.xstate = XmlState.EnumAttrs; 
            this.depth--;
        }

        ///  
        /// Add a new namespace declaration -- xmlns:prefix="ns" -- to the set of in-scope declarations.
        /// NOTE: This method should only be called if caller can guarantee that the current state is EnumAttrs 
        ///       and that there will be no namespace conflicts in the current scope (e.g. trying to map the 
        ///       same prefix to different namespaces within the same element start tag).  If no such
        ///       guarantees exist, then WriteNamespaceDeclaration() should be called instead. 
        /// 
        public void WriteNamespaceDeclarationUnchecked(string prefix, string ns) {
            Debug.Assert(prefix != null && ns != null);
            Debug.Assert(this.xstate == XmlState.EnumAttrs, "WriteNamespaceDeclaration cannot be called in the " + this.xstate + " state."); 

            // xmlns:foo="" is illegal 
            Debug.Assert(prefix.Length == 0 || ns.Length != 0); 

            if (this.depth == 0) { 
                // At top-level, so write namespace declaration directly to output
                Writer.WriteNamespaceDeclaration(prefix, ns);
                return;
            } 

            if (this.nsmgr == null) { 
                // If namespace manager has no namespaces, then xmlns="" is in scope by default 
                if (ns.Length == 0 && prefix.Length == 0)
                    return; 

                this.nsmgr = new XmlNamespaceManager(this.runtime.NameTable);
                this.nsmgr.PushScope();
            } 

            if (this.nsmgr.LookupNamespace(prefix) != ns) 
                AddNamespace(prefix, ns); 
        }
 
        /// 
        /// Write a text block to the XmlRawWriter.
        /// 
        public void WriteStringUnchecked(string text) { 
            Debug.Assert(this.xstate != XmlState.WithinSequence && this.xstate != XmlState.EnumAttrs, "WriteTextBlock cannot be called in the " + this.xstate + " state.");
            Writer.WriteString(text); 
        } 

        ///  
        /// Write a text block without escaping special characters.
        /// 
        public void WriteRawUnchecked(string text) {
            Debug.Assert(this.xstate != XmlState.WithinSequence && this.xstate != XmlState.EnumAttrs, "WriteTextBlockNoEntities cannot be called in the " + this.xstate + " state."); 
            Writer.WriteRaw(text);
        } 
 

        //----------------------------------------------- 
        // XmlQueryOutput methods
        //-----------------------------------------------

        ///  
        /// Before calling XmlSequenceWriter.StartTree(), perform checks to ensure well-formedness.
        ///  
        public void WriteStartRoot() { 
            Debug.Assert(this.depth == 0, "Root node can only be constructed at top-level.");
            if (this.xstate != XmlState.WithinSequence) 
                ThrowInvalidStateError(XPathNodeType.Root);

            StartTree(XPathNodeType.Root);
            this.depth++; 
        }
 
        ///  
        /// Call XmlSequenceWriter.EndTree() and reset state.
        ///  
        public void WriteEndRoot() {
            Debug.Assert(this.depth == 1, "Root node can only be constructed at top-level.");
            this.depth--;
            EndTree(); 
        }
 
        ///  
        /// WriteStartElement() with empty prefix, ns.
        ///  
        public void WriteStartElementLocalName(string localName) {
            WriteStartElement(string.Empty, localName, string.Empty);
        }
 
        /// 
        /// WriteStartAttribute() with empty prefix, ns, and null schema type. 
        ///  
        public void WriteStartAttributeLocalName(string localName) {
            WriteStartAttribute(string.Empty, localName, string.Empty); 
        }

        /// 
        /// Write an element with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings. 
        /// 
        public void WriteStartElementComputed(string tagName, int prefixMappingsIndex) { 
            WriteStartComputed(XPathNodeType.Element, tagName, prefixMappingsIndex); 
        }
 
        /// 
        /// Write an element with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        /// 
        public void WriteStartElementComputed(string tagName, string ns) { 
            WriteStartComputed(XPathNodeType.Element, tagName, ns);
        } 
 
        /// 
        /// Write an element with a name that is copied from the navigator. 
        /// 
        public void WriteStartElementComputed(XPathNavigator navigator) {
            WriteStartComputed(XPathNodeType.Element, navigator);
        } 

        ///  
        /// Write an element with a name that is derived from the XmlQualifiedName. 
        /// 
        public void WriteStartElementComputed(XmlQualifiedName name) { 
            WriteStartComputed(XPathNodeType.Element, name);
        }

        ///  
        /// Write an attribute with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings.
        ///  
        public void WriteStartAttributeComputed(string tagName, int prefixMappingsIndex) { 
            WriteStartComputed(XPathNodeType.Attribute, tagName, prefixMappingsIndex);
        } 

        /// 
        /// Write an attribute with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        ///  
        public void WriteStartAttributeComputed(string tagName, string ns) {
            WriteStartComputed(XPathNodeType.Attribute, tagName, ns); 
        } 

        ///  
        /// Write an attribute with a name that is copied from the navigator.
        /// 
        public void WriteStartAttributeComputed(XPathNavigator navigator) {
            WriteStartComputed(XPathNodeType.Attribute, navigator); 
        }
 
        ///  
        /// Write an attribute with a name that is derived from the XmlQualifiedName.
        ///  
        public void WriteStartAttributeComputed(XmlQualifiedName name) {
            WriteStartComputed(XPathNodeType.Attribute, name);
        }
 
        /// 
        /// Before calling XmlRawWriter.WriteNamespaceDeclaration(), perform various checks to ensure well-formedness. 
        ///  
        public void WriteNamespaceDeclaration(string prefix, string ns) {
            string nsExisting; 
            Debug.Assert(prefix != null && ns != null);

            ConstructInEnumAttrs(XPathNodeType.Namespace);
 
            if (this.nsmgr == null) {
                // If namespace manager has not yet been created, then there is no possibility of conflict 
                WriteNamespaceDeclarationUnchecked(prefix, ns); 
            }
            else { 
                nsExisting = this.nsmgr.LookupNamespace(prefix);
                if (ns != nsExisting) {
                    // prefix = "", ns = "", nsExisting --> Look for xmlns="", found xmlns="foo"
                    // prefix = "", ns, nsExisting = null --> Look for xmlns="uri", no uri found 
                    // prefix = "", ns, nsExisting = "" --> Look for xmlns="uri", found xmlns=""
                    // prefix = "", ns, nsExisting --> Look for xmlns="uri", found xmlns="uri2" 
                    // prefix, ns, nsExisting = null --> Look for xmlns:foo="uri", no uri found 
                    // prefix, ns, nsExisting --> Look for xmlns:foo="uri", found xmlns:foo="uri2"
 
                    // If the prefix is mapped to a uri,
                    if (nsExisting != null) {
                        // Then throw an error except in a special case involving default namespace declaration
                        // Looking for xmlns="", found xmlns="foo" -- ERROR 
                        // Looking for xmlns="uri", found xmlns="uri2" -- ERROR
                        // Looking for xmlns="uri", found xmlns="" -- OK, unless xmlns="" declaration is 
                        //                                            local or element's namespace is "" 
                        if (prefix.Length != 0 || nsExisting.Length != 0 || this.useDefNmsp)
                            throw new XslTransformException(Res.XmlIl_NmspConflict, new string[] {prefix.Length == 0 ? "" : ":", prefix, ns, nsExisting}); 
                    }

                    // Add namespace to manager and write it to output
                    AddNamespace(prefix, ns); 
                }
            } 
 
            if (this.depth == 0)
                EndTree(); 
        }

        /// 
        /// Before writing a namespace, perform various checks to ensure well-formedness. 
        /// 
        public void WriteStartNamespace(string prefix) { 
            Debug.Assert(prefix != null, "Invalid argument"); 

            // Handle namespace attributes that are not sent directly to WriteNamespaceDeclaration 
            ConstructInEnumAttrs(XPathNodeType.Namespace);
            this.piTarget/*nmspPrefix*/ = prefix;
            this.nodeText.Clear();
 
            this.xstate = XmlState.WithinNmsp;
            this.depth++; 
        } 

        ///  
        /// Cache the namespace's text.
        /// 
        public void WriteNamespaceString(string text) {
            Debug.Assert(this.xstate == XmlState.WithinNmsp, "WriteNamespaceString cannot be called in the " + this.xstate + " state."); 
            this.nodeText.ConcatNoDelimiter(text);
        } 
 
        /// 
        /// Before writing a namespace, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndNamespace() {
            Debug.Assert(this.xstate == XmlState.WithinNmsp, "WriteEndNamespace cannot be called in the " + this.xstate + " state.");
 
            this.xstate = XmlState.EnumAttrs;
            this.depth--; 
 
            // Write cached namespace attribute
            WriteNamespaceDeclaration(this.piTarget/*nmspPrefix*/, this.nodeText.GetResult()); 

            if (this.depth == 0)
                EndTree();
        } 

        ///  
        /// Before writing a comment, perform various checks to ensure well-formedness. 
        /// 
        public void WriteStartComment() { 
            // Xml state transitions
            ConstructWithinContent(XPathNodeType.Comment);

            this.nodeText.Clear(); 
            this.xstate = XmlState.WithinComment;
            this.depth++; 
        } 

        ///  
        /// Cache the comment's text.
        /// 
        public void WriteCommentString(string text) {
            Debug.Assert(this.xstate == XmlState.WithinComment, "WriteCommentString cannot be called in the " + this.xstate + " state."); 
            this.nodeText.ConcatNoDelimiter(text);
        } 
 
        /// 
        /// Before writing a comment, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndComment() {
            Debug.Assert(this.xstate == XmlState.WithinComment, "WriteEndComment cannot be called in the " + this.xstate + " state.");
 
            Writer.WriteComment(this.nodeText.GetResult());
 
            this.xstate = XmlState.WithinContent; 
            this.depth--;
 
            if (this.depth == 0)
                EndTree();
        }
 
        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness. 
        ///  
        public void WriteStartProcessingInstruction(string target) {
            // Xml state transitions 
            ConstructWithinContent(XPathNodeType.ProcessingInstruction);

            // Verify PI name
            ValidateNames.ValidateNameThrow("", target, "", XPathNodeType.ProcessingInstruction, ValidateNames.Flags.AllExceptPrefixMapping); 

            this.piTarget = target; 
            this.nodeText.Clear(); 

            this.xstate = XmlState.WithinPI; 
            this.depth++;
        }

        ///  
        /// Cache the processing instruction's text.
        ///  
        public void WriteProcessingInstructionString(string text) { 
            Debug.Assert(this.xstate == XmlState.WithinPI, "WriteProcessingInstructionString cannot be called in the " + this.xstate + " state.");
            this.nodeText.ConcatNoDelimiter(text); 
        }

        /// 
        /// Before writing a processing instruction, perform various checks to ensure well-formedness. 
        /// 
        public void WriteEndProcessingInstruction() { 
            Debug.Assert(this.xstate == XmlState.WithinPI, "WriteEndProcessingInstruction cannot be called in the " + this.xstate + " state."); 

            Writer.WriteProcessingInstruction(this.piTarget, this.nodeText.GetResult()); 

            this.xstate = XmlState.WithinContent;
            this.depth--;
 
            // Xml state transitions
            if (this.depth == 0) 
                EndTree(); 
        }
 
        /// 
        /// Write an item to output.  If currently constructing an Xml tree, then the item is always copied.
        /// At the top-level, the item's identity is preserved unless it's an atomic value.
        ///  
        public void WriteItem(XPathItem item) {
            if (item.IsNode) { 
                XPathNavigator navigator = (XPathNavigator) item; 

                // If this is a top-level node, write a reference to it; else copy it by value 
                if (this.xstate == XmlState.WithinSequence)
                    this.seqwrt.WriteItem(navigator);
                else
                    CopyNode(navigator); 
            }
            else { 
                // Call WriteItem for atomic values 
                Debug.Assert(this.xstate == XmlState.WithinSequence, "Values can only be written at the top-level.");
                this.seqwrt.WriteItem(item); 
            }
        }

        ///  
        /// Copy a node by value to output according to Xslt rules:
        ///   1. Identity is never preserved 
        ///   2. If the item is an Rtf, preserve serialization hints when copying. 
        ///   3. If the item is a Root node, copy the children of the Root
        ///  
        public void XsltCopyOf(XPathNavigator navigator) {
            RtfNavigator navRtf = navigator as RtfNavigator;

            if (navRtf != null) { 
                // Copy Rtf
                navRtf.CopyToWriter(this); 
            } 
            else if (navigator.NodeType == XPathNodeType.Root) {
                // Copy children of root 
                if (navigator.MoveToFirstChild()) {
                    do {
                        CopyNode(navigator);
                    } 
                    while (navigator.MoveToNext());
 
                    navigator.MoveToParent(); 
                }
            } 
            else {
                // Copy node
                CopyNode(navigator);
            } 
        }
 
        ///  
        /// Begin shallow copy of the navigator's current node to output.  Returns true if EndCopy
        /// should be called to complete the copy operation. 
        /// Automatically copies all in-scope namespaces on elements.
        /// 
        public bool StartCopy(XPathNavigator navigator) {
            // StartDocument is a no-op 
            if (navigator.NodeType == XPathNodeType.Root)
                return true; 
 
            if (StartCopy(navigator, true)) {
                Debug.Assert(navigator.NodeType == XPathNodeType.Element, "StartCopy should return true only for Element nodes."); 

                // Copy namespaces to output
                CopyNamespaces(navigator, XPathNamespaceScope.ExcludeXml);
 
                return true;
            } 
 
            return false;
        } 

        /// 
        /// End shallow copy of the navigator's current node.  Should be called only for Element and Document nodes.
        ///  
        public void EndCopy(XPathNavigator navigator) {
            if (navigator.NodeType == XPathNodeType.Element) 
                WriteEndElement(); 
            else
                Debug.Assert(navigator.NodeType == XPathNodeType.Root, "EndCopy should only be called for Element and Document nodes."); 
        }


        //----------------------------------------------- 
        // Helper methods
        //----------------------------------------------- 
 
        /// 
        /// Add an in-scope namespace. 
        /// 
        private void AddNamespace(string prefix, string ns) {
            this.nsmgr.AddNamespace(prefix, ns);
            this.cntNmsp++; 
            if (ns.Length == 0)
                this.useDefNmsp = true; 
        } 

        ///  
        /// Before writing text, perform various checks to ensure well-formedness.
        /// 
        private void WriteString(string text, bool disableOutputEscaping) {
            Debug.Assert(text != null, "Invalid argument"); 

            // Xml state transitions 
            switch (this.xstate) { 
                case XmlState.WithinSequence:
                    // Start constructing new tree 
                    StartTree(XPathNodeType.Text);
                    goto case XmlState.WithinContent;

                case XmlState.WithinContent: 
                    if (disableOutputEscaping)
                        WriteRawUnchecked(text); 
                    else 
                        WriteStringUnchecked(text);
                    break; 

                case XmlState.EnumAttrs:
                    // Enumerating attributes, so write text as element content
                    StartElementContentUnchecked(); 
                    goto case XmlState.WithinContent;
 
                case XmlState.WithinAttr: 
                    WriteStringUnchecked(text);
                    break; 

                case XmlState.WithinNmsp:
                    WriteNamespaceString(text);
                    break; 

                case XmlState.WithinComment: 
                    // Comment text 
                    WriteCommentString(text);
                    break; 

                case XmlState.WithinPI:
                    // PI text
                    WriteProcessingInstructionString(text); 
                    break;
 
                default: 
                    Debug.Assert(false, "Text cannot be output in the " + this.xstate + " state.");
                    break; 
            }

            if (this.depth == 0)
                EndTree(); 
        }
 
        ///  
        /// Deep copy the subtree that is rooted at this navigator's current position to output.  If the current
        /// item is an element, copy all in-scope namespace nodes. 
        /// 
        private void CopyNode(XPathNavigator navigator) {
            XPathNodeType nodeType;
            int depthStart = this.depth; 
            Debug.Assert(navigator != null);
 
            while (true) { 
                if (StartCopy(navigator, this.depth == depthStart)) {
                    nodeType = navigator.NodeType; 
                    Debug.Assert(nodeType == XPathNodeType.Element, "StartCopy should return true only for Element nodes.");

                    // Copy attributes
                    if (navigator.MoveToFirstAttribute()) { 
                        do {
                            StartCopy(navigator, false); 
                        } 
                        while (navigator.MoveToNextAttribute());
                        navigator.MoveToParent(); 
                    }

                    // Copy namespaces in document order (navigator returns them in reverse document order)
                    CopyNamespaces(navigator, (this.depth - 1 == depthStart) ? XPathNamespaceScope.ExcludeXml : XPathNamespaceScope.Local); 

                    StartElementContentUnchecked(); 
 
                    // If children exist, move down to next level
                    if (navigator.MoveToFirstChild()) 
                        continue;

                    EndCopy(navigator, (this.depth - 1) == depthStart);
                } 

                // No children 
                while (true) { 
                    if (this.depth == depthStart) {
                        // The entire subtree has been copied 
                        return;
                    }

                    if (navigator.MoveToNext()) { 
                        // Found a sibling, so break to outer loop
                        break; 
                    } 

                    // No siblings, so move up to previous level 
                    navigator.MoveToParent();

                    EndCopy(navigator, (this.depth - 1) == depthStart);
                } 
            }
        } 
 
        /// 
        /// Begin shallow copy of the navigator's current node to output.  Returns true if EndCopy 
        /// should be called to complete the copy operation.
        /// 
        private bool StartCopy(XPathNavigator navigator, bool callChk) {
            bool mayHaveChildren = false; 

            switch (navigator.NodeType) { 
                case XPathNodeType.Element: 
                    // If checks need to be made, call XmlQueryOutput.WriteStartElement
                    if (callChk) { 
                        WriteStartElement(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI);
                    }
                    else {
                        WriteStartElementUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
 
                    mayHaveChildren = true; 
                    break;
 
                case XPathNodeType.Attribute:
                    // If checks need to be made, call XmlQueryOutput.WriteStartAttribute
                    if (callChk) {
                        WriteStartAttribute(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
                    else { 
                        WriteStartAttributeUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
                    }
 
                    // Write attribute text
                    WriteString(navigator.Value);

                    // If checks need to be made, call XmlQueryOutput.WriteEndAttribute 
                    if (callChk) {
                        WriteEndAttribute(); 
                    } 
                    else {
                        WriteEndAttributeUnchecked(); 
                    }
                    break;

                case XPathNodeType.Namespace: 
                    // If checks need to be made, call XmlQueryOutput.WriteNamespaceDeclaration
                    if (callChk) { 
                        // Do not allow namespaces to be copied after attributes 
                        XmlAttributeCache attrCache = Writer as XmlAttributeCache;
                        if (attrCache != null && attrCache.Count != 0) 
                            throw new XslTransformException(Res.XmlIl_NmspAfterAttr, string.Empty);

                        WriteNamespaceDeclaration(navigator.LocalName, navigator.Value);
                    } 
                    else {
                        WriteNamespaceDeclarationUnchecked(navigator.LocalName, navigator.Value); 
                    } 
                    break;
 
                case XPathNodeType.Text:
                case XPathNodeType.SignificantWhitespace:
                case XPathNodeType.Whitespace:
                    // If checks need to be made, call XmlQueryOutput.WriteString 
                    if (callChk) {
                        WriteString(navigator.Value, false); 
                    } 
                    else {
                        // No flags are set, so this is simple element text (attributes, comments, pi's copy own text) 
                        WriteStringUnchecked(navigator.Value);
                    }
                    break;
 
                case XPathNodeType.Root:
                    // Document node is invalid except at the top-level 
                    Debug.Assert(this.xstate != XmlState.WithinSequence, "StartCopy should not called if state is WithinSequence"); 
                    ThrowInvalidStateError(XPathNodeType.Root);
                    break; 

                case XPathNodeType.Comment:
                    WriteStartComment();
                    WriteCommentString(navigator.Value); 
                    WriteEndComment();
                    break; 
 
                case XPathNodeType.ProcessingInstruction:
                    WriteStartProcessingInstruction(navigator.LocalName); 
                    WriteProcessingInstructionString(navigator.Value);
                    WriteEndProcessingInstruction();
                    break;
 
                default:
                    Debug.Assert(false); 
                    break; 
            }
 
            return mayHaveChildren;
        }

        ///  
        /// End shallow copy of the navigator's current node to output.  This method should only be called if StartCopy
        /// returned true. 
        ///  
        private void EndCopy(XPathNavigator navigator, bool callChk) {
            Debug.Assert(navigator.NodeType == XPathNodeType.Element); 
            Debug.Assert(this.xstate == XmlState.WithinContent, "EndCopy cannot be called in the " + this.xstate + " state.");

            if (callChk)
                WriteEndElement(); 
            else
                WriteEndElementUnchecked(navigator.Prefix, navigator.LocalName, navigator.NamespaceURI); 
        } 

        ///  
        /// Copy all namespaces of the specified type (in-scope, exclude-xml, local) in document order to output.
        /// 
        private void CopyNamespaces(XPathNavigator navigator, XPathNamespaceScope nsScope) {
            Debug.Assert(navigator.NodeType == XPathNodeType.Element, "Only elements have namespaces to copy"); 

            // Default namespace undeclaration isn't included in navigator's namespace list, so add it now 
            if (navigator.NamespaceURI.Length == 0) { 
                Debug.Assert(navigator.LocalName.Length != 0, "xmlns:foo='' isn't allowed");
                WriteNamespaceDeclarationUnchecked(string.Empty, string.Empty); 
            }

            // Since the namespace list is arranged in reverse-document order, recursively reverse it.
            if (navigator.MoveToFirstNamespace(nsScope)) { 
                CopyNamespacesHelper(navigator, nsScope);
                navigator.MoveToParent(); 
            } 
        }
 
        /// 
        /// Recursive helper function that reverses order of the namespaces retrieved by MoveToFirstNamespace and
        /// MoveToNextNamespace.
        ///  
        private void CopyNamespacesHelper(XPathNavigator navigator, XPathNamespaceScope nsScope) {
            string prefix = navigator.LocalName; 
            string ns = navigator.Value; 

            if (navigator.MoveToNextNamespace(nsScope)) 
                CopyNamespacesHelper(navigator, nsScope);

            // No possibility for conflict, since we're copying namespaces from well-formed element
            WriteNamespaceDeclarationUnchecked(prefix, ns); 
        }
 
        ///  
        /// Ensure that state transitions to WithinContent.
        ///  
        private void ConstructWithinContent(XPathNodeType rootType) {
            Debug.Assert(rootType == XPathNodeType.Element || rootType == XPathNodeType.Comment || rootType == XPathNodeType.ProcessingInstruction);

            switch (this.xstate) { 
                case XmlState.WithinSequence:
                    // If state is WithinSequence, call XmlSequenceWriter.StartTree 
                    StartTree(rootType); 
                    this.xstate = XmlState.WithinContent;
                    break; 

                case XmlState.WithinContent:
                    // Already within element content
                    break; 

                case XmlState.EnumAttrs: 
                    // Start element content 
                    StartElementContentUnchecked();
                    break; 

                default:
                    // Construction is not allowed in this state
                    ThrowInvalidStateError(rootType); 
                    break;
            } 
        } 

        ///  
        /// Ensure that state transitions to EnumAttrs.
        /// 
        private void ConstructInEnumAttrs(XPathNodeType rootType) {
            Debug.Assert(rootType == XPathNodeType.Attribute || rootType == XPathNodeType.Namespace); 

            switch (this.xstate) { 
                case XmlState.WithinSequence: 
                    StartTree(rootType);
                    this.xstate = XmlState.EnumAttrs; 
                    break;

                case XmlState.EnumAttrs:
                    // Already in EnumAttrs state 
                    break;
 
                default: 
                    // Construction is not allowed in this state
                    ThrowInvalidStateError(rootType); 
                    break;
            }
        }
 
        /// 
        /// Namespace declarations are added to this.nsmgr.  Just before element content has begun, write out 
        /// all namespaces that were declared locally on the element. 
        /// 
        private void WriteCachedNamespaces() { 
            string prefix, ns;

            while (this.cntNmsp != 0) {
                // Output each prefix->ns mapping pair 
                Debug.Assert(this.nsmgr != null);
                this.cntNmsp--; 
                this.nsmgr.GetNamespaceDeclaration(this.cntNmsp, out prefix, out ns); 
                Writer.WriteNamespaceDeclaration(prefix, ns);
            } 
        }

        /// 
        /// Return the type of node that is under construction given the specified XmlState. 
        /// 
        private XPathNodeType XmlStateToNodeType(XmlState xstate) { 
            switch (xstate) { 
                case XmlState.EnumAttrs: return XPathNodeType.Element;
                case XmlState.WithinContent: return XPathNodeType.Element; 
                case XmlState.WithinAttr: return XPathNodeType.Attribute;
                case XmlState.WithinComment: return XPathNodeType.Comment;
                case XmlState.WithinPI: return XPathNodeType.ProcessingInstruction;
            } 

            Debug.Assert(false, xstate.ToString() + " is not a valid XmlState."); 
            return XPathNodeType.Element; 
        }
 
        /// 
        /// If attribute's prefix conflicts with other prefixes then redeclare the prefix.  If the prefix has
        /// not yet been declared, then add it to the namespace manager.
        ///  
        private string CheckAttributePrefix(string prefix, string ns) {
            string nsExisting; 
            Debug.Assert(prefix.Length != 0 && ns.Length != 0); 

            // Ensure that this attribute's prefix does not conflict with previously declared prefixes in this scope 
            if (this.nsmgr == null) {
                // If namespace manager has no namespaces, then there is no possibility of conflict
                WriteNamespaceDeclarationUnchecked(prefix, ns);
            } 
            else {
                while (true) { 
                    // If prefix is already mapped to a different namespace, 
                    nsExisting = this.nsmgr.LookupNamespace(prefix);
                    if (nsExisting != ns) { 

                        // Then if the prefix is already mapped,
                        if (nsExisting != null) {
                            // Then there is a conflict that must be resolved by finding another prefix 
                            // Always find a new prefix, even if the conflict didn't occur in the current scope
                            // This decision allows more aggressive namespace analysis at compile-time 
                            prefix = RemapPrefix(prefix, ns, false); 
                            continue;
                        } 

                        // Add the mapping to the current scope
                        AddNamespace(prefix, ns);
                    } 
                    break;
                } 
            } 

            return prefix; 
        }

        /// 
        /// Remaps an element or attribute prefix using the following rules: 
        ///
        ///   1. If another in-scope prefix is already mapped to "ns", then use that 
        ///   2. Otherwise, if a prefix was previously mapped to "ns" by this method, then use that 
        ///   3. Otherwise, generate a new prefix of the form 'xp_??', where ?? is a stringized counter
        /// 
        /// These rules tend to reduce the number of unique prefixes used throughout the tree.
        /// 
        private string RemapPrefix(string prefix, string ns, bool isElemPrefix) {
            const string PrefixFormat = "xp_{0}"; 
            string genPrefix;
            Debug.Assert(prefix != null && ns != null && ns.Length != 0); 
 
            if (this.conflictPrefixes == null)
                this.conflictPrefixes = new Hashtable(16); 

            if (this.nsmgr == null) {
                this.nsmgr = new XmlNamespaceManager(this.runtime.NameTable);
                this.nsmgr.PushScope(); 
            }
 
            // Rule #1: If another in-scope prefix is already mapped to "ns", then use that 
            genPrefix = this.nsmgr.LookupPrefix(ns);
            if (genPrefix != null) { 
                // Can't use an empty prefix for an attribute
                if (isElemPrefix || genPrefix.Length != 0)
                    goto ReturnPrefix;
            } 

            // Rule #2: Otherwise, if a prefix was previously mapped to "ns" by this method, then use that 
            // Make sure that any previous prefix is different than "prefix" 
            genPrefix = this.conflictPrefixes[ns] as string;
            if (genPrefix != null && genPrefix != prefix) { 
                // Can't use an empty prefix for an attribute
                if (isElemPrefix || genPrefix.Length != 0)
                    goto ReturnPrefix;
            } 

            // Rule #3: Otherwise, generate a new prefix of the form 'xp_??', where ?? is a stringized counter 
            genPrefix = string.Format(CultureInfo.InvariantCulture, PrefixFormat, this.prefixIndex++); 

        ReturnPrefix: 
            // Save generated prefix so that it can be possibly be reused later
            this.conflictPrefixes[ns] = genPrefix;

            return genPrefix; 
        }
 
        ///  
        /// Write an element or attribute with a name that is computed from a "prefix:localName" tag name and a set of prefix mappings.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, string tagName, int prefixMappingsIndex) {
            string prefix, localName, ns;

            // Parse the tag name and map the prefix to a namespace 
            runtime.ParseTagName(tagName, prefixMappingsIndex, out prefix, out localName, out ns);
 
            // Validate the name parts 
            prefix = EnsureValidName(prefix, localName, ns, nodeType);
 
            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, localName, ns);
            else
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        ///  
        /// Write an element or attribute with a name that is computed from a "prefix:localName" tag name and a namespace URI.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, string tagName, string ns) {
            string prefix, localName;

            // Parse the tagName as a prefix, localName pair 
            ValidateNames.ParseQNameThrow(tagName, out prefix, out localName);
 
            // Validate the name parts 
            prefix = EnsureValidName(prefix, localName, ns, nodeType);
 
            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, localName, ns);
            else
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        ///  
        /// Write an element or attribute with a name that is copied from the navigator.
        ///  
        private void WriteStartComputed(XPathNodeType nodeType, XPathNavigator navigator) {
            string prefix, localName, ns;

            prefix = navigator.Prefix; 
            localName = navigator.LocalName;
            ns = navigator.NamespaceURI; 
 
            if (navigator.NodeType != nodeType) {
                // Validate the name parts 
                prefix = EnsureValidName(prefix, localName, ns, nodeType);
            }

            if (nodeType == XPathNodeType.Element) 
                WriteStartElement(prefix, localName, ns);
            else 
                WriteStartAttribute(prefix, localName, ns); 
        }
 
        /// 
        /// Write an element or attribute with a name that is derived from the XmlQualifiedName.
        /// 
        private void WriteStartComputed(XPathNodeType nodeType, XmlQualifiedName name) { 
            string prefix;
            Debug.Assert(ValidateNames.ParseNCName(name.Name, 0) == name.Name.Length); 
 
            // Validate the name parts
            prefix = (name.Namespace.Length != 0) ? RemapPrefix(string.Empty, name.Namespace, nodeType == XPathNodeType.Element) : string.Empty; 
            prefix = EnsureValidName(prefix, name.Name, name.Namespace, nodeType);

            if (nodeType == XPathNodeType.Element)
                WriteStartElement(prefix, name.Name, name.Namespace); 
            else
                WriteStartAttribute(prefix, name.Name, name.Namespace); 
        } 

        ///  
        /// Ensure that the specified name parts are valid according to Xml 1.0 and Namespace 1.0 rules.  Try to remap
        /// the prefix in order to attain validity.  Throw if validity is not possible.  Otherwise, return the (possibly
        /// remapped) prefix.
        ///  
        private string EnsureValidName(string prefix, string localName, string ns, XPathNodeType nodeType) {
            if (!ValidateNames.ValidateName(prefix, localName, ns, nodeType, ValidateNames.Flags.AllExceptNCNames)) { 
                // Name parts are not valid as is.  Try to re-map the prefix. 
                prefix = (ns.Length != 0) ? RemapPrefix(string.Empty, ns, nodeType == XPathNodeType.Element) : string.Empty;
 
                // Throw if validation does not work this time
                ValidateNames.ValidateNameThrow(prefix, localName, ns, nodeType, ValidateNames.Flags.AllExceptNCNames);
            }
 
            return prefix;
        } 
 
        /// 
        /// Push element name parts onto the stack. 
        /// 
        private void PushElementNames(string prefix, string localName, string ns) {
            // Push the name parts onto a stack
            if (this.stkNames == null) 
                this.stkNames = new Stack();
 
            this.stkNames.Push(prefix); 
            this.stkNames.Push(localName);
            this.stkNames.Push(ns); 
        }

        /// 
        /// Pop element name parts from the stack. 
        /// 
        private void PopElementNames(out string prefix, out string localName, out string ns) { 
            Debug.Assert(this.stkNames != null); 

            ns = this.stkNames.Pop() as string; 
            localName = this.stkNames.Pop() as string;
            prefix = this.stkNames.Pop() as string;
        }
 
        /// 
        /// Throw an invalid state transition error. 
        ///  
        private void ThrowInvalidStateError(XPathNodeType constructorType) {
            switch (constructorType) { 
                case XPathNodeType.Element:
                case XPathNodeType.Root:
                case XPathNodeType.Text:
                case XPathNodeType.Comment: 
                case XPathNodeType.ProcessingInstruction:
                    throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {constructorType.ToString(), XmlStateToNodeType(this.xstate).ToString()}); 
 
                case XPathNodeType.Attribute:
                case XPathNodeType.Namespace: 
                    if (this.depth == 1)
                        throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {constructorType.ToString(), this.rootType.ToString()});

                    if (this.xstate == XmlState.WithinContent) 
                        throw new XslTransformException(Res.XmlIl_BadXmlStateAttr, string.Empty);
 
                    goto case XPathNodeType.Element; 

                default: 
                    throw new XslTransformException(Res.XmlIl_BadXmlState, new string[] {"Unknown", XmlStateToNodeType(this.xstate).ToString()});
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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