DocumentXmlWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Xml / System / Xml / Dom / DocumentXmlWriter.cs / 1 / DocumentXmlWriter.cs

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

namespace System.Xml { 
    enum DocumentXmlWriterType {
        InsertSiblingAfter, 
        InsertSiblingBefore, 
        PrependChild,
        AppendChild, 
        AppendAttribute,
        ReplaceToFollowingSibling,
    }
 
    // Implements a XmlWriter that augments a XmlDocument.
    sealed class DocumentXmlWriter : XmlRawWriter, IXmlNamespaceResolver { 
        enum State { 
            Error,
            Attribute, 
            Prolog,
            Fragment,
            Content,
 
            Last, // always last
        } 
 
        enum Method {
            WriteXmlDeclaration, 
            WriteStartDocument,
            WriteEndDocument,
            WriteDocType,
            WriteStartElement, 
            WriteEndElement,
            WriteFullEndElement, 
            WriteStartAttribute, 
            WriteEndAttribute,
            WriteNamespaceDeclaration, 
            WriteCData,
            WriteComment,
            WriteProcessingInstruction,
            WriteEntityRef, 
            WriteWhitespace,
            WriteString, 
        } 

        DocumentXmlWriterType type; // writer type 
        XmlNode start; // context node
        XmlDocument document; // context document
        XmlNamespaceManager namespaceManager; // context namespace manager
        State state; // current state 
        XmlNode write; // current node
        List fragment; // top level node cache 
        XmlWriterSettings settings; // wrapping writer settings 
        DocumentXPathNavigator navigator; // context for replace
        XmlNode end; // context for replace 

        public DocumentXmlWriter(DocumentXmlWriterType type, XmlNode start, XmlDocument document) {
            this.type = type;
            this.start = start; 
            this.document = document;
 
            state = StartState(); 
            fragment = new List();
            settings = new XmlWriterSettings(); 
            settings.ReadOnly = false;
            settings.CheckCharacters = false;
            settings.CloseOutput = false;
            settings.ConformanceLevel = (state == State.Prolog ? ConformanceLevel.Document : ConformanceLevel.Fragment); 
            settings.ReadOnly = true;
        } 
 
        public XmlNamespaceManager NamespaceManager {
            set { 
                namespaceManager = value;
            }
        }
 
        public override XmlWriterSettings Settings {
            get { 
                return settings; 
            }
        } 

        internal void SetSettings(XmlWriterSettings value) {
            settings = value;
        } 

        public DocumentXPathNavigator Navigator { 
            set { 
                navigator = value;
            } 
        }

        public XmlNode EndNode {
            set { 
                end = value;
            } 
        } 

        internal override void WriteXmlDeclaration(XmlStandalone standalone) { 
            VerifyState(Method.WriteXmlDeclaration);
            if (standalone != XmlStandalone.Omit) {
                XmlNode node = document.CreateXmlDeclaration("1.0", string.Empty, standalone == XmlStandalone.Yes ? "yes" : "no");
                AddChild(node, write); 
            }
        } 
 
        internal override void WriteXmlDeclaration(string xmldecl) {
            VerifyState(Method.WriteXmlDeclaration); 
            string version, encoding, standalone;
            XmlLoader.ParseXmlDeclarationValue(xmldecl, out version, out encoding, out standalone);
            XmlNode node = document.CreateXmlDeclaration(version, encoding, standalone);
            AddChild(node, write); 
        }
 
        public override void WriteStartDocument() { 
            VerifyState(Method.WriteStartDocument);
        } 

        public override void WriteStartDocument(bool standalone) {
            VerifyState(Method.WriteStartDocument);
        } 

        public override void WriteEndDocument() { 
            VerifyState(Method.WriteEndDocument); 
        }
 
        public override void WriteDocType(string name, string pubid, string sysid, string subset) {
            VerifyState(Method.WriteDocType);
            XmlNode node = document.CreateDocumentType(name, pubid, sysid, subset);
            AddChild(node, write); 
        }
 
        public override void WriteStartElement(string prefix, string localName, string ns) { 
            VerifyState(Method.WriteStartElement);
            XmlNode node = document.CreateElement(prefix, localName, ns); 
            AddChild(node, write);
            write = node;
        }
 
        public override void WriteEndElement() {
            VerifyState(Method.WriteEndElement); 
            if (write == null) { 
                throw new InvalidOperationException();
            } 
            write = write.ParentNode;
        }

        internal override void WriteEndElement(string prefix, string localName, string ns) { 
            WriteEndElement();
        } 
 
        public override void WriteFullEndElement() {
            VerifyState(Method.WriteFullEndElement); 
            XmlElement elem = write as XmlElement;
            if (elem == null) {
                throw new InvalidOperationException();
            } 
            elem.IsEmpty = false;
            write = elem.ParentNode; 
        } 

        internal override void WriteFullEndElement(string prefix, string localName, string ns) { 
            WriteFullEndElement();
        }

        internal override void StartElementContent() { 
            // nop
        } 
 
        public override void WriteStartAttribute(string prefix, string localName, string ns) {
            VerifyState(Method.WriteStartAttribute); 
            XmlAttribute attr = document.CreateAttribute(prefix, localName, ns);
            AddAttribute(attr, write);
            write = attr;
        } 

        public override void WriteEndAttribute() { 
            VerifyState(Method.WriteEndAttribute); 
            XmlAttribute attr = write as XmlAttribute;
            if (attr == null) { 
                throw new InvalidOperationException();
            }
            if (!attr.HasChildNodes) {
                XmlNode node = document.CreateTextNode(string.Empty); 
                AddChild(node, attr);
            } 
            write = attr.OwnerElement; 
        }
 
        internal override void WriteNamespaceDeclaration(string prefix, string ns) {
            VerifyState(Method.WriteNamespaceDeclaration);
            XmlAttribute attr;
            if (prefix.Length == 0) { 
                attr = document.CreateAttribute(prefix, document.strXmlns, document.strReservedXmlns);
            } 
            else { 
                attr = document.CreateAttribute(document.strXmlns, prefix, document.strReservedXmlns);
            } 
            AddAttribute(attr, write);
            XmlNode node = document.CreateTextNode(ns);
            AddChild(node, attr);
        } 

        public override void WriteCData(string text) { 
            VerifyState(Method.WriteCData); 
            XmlConvert.VerifyCharData(text, ExceptionType.ArgumentException);
            XmlNode node = document.CreateCDataSection(text); 
            AddChild(node, write);
        }

        public override void WriteComment(string text) { 
            VerifyState(Method.WriteComment);
            XmlConvert.VerifyCharData(text, ExceptionType.ArgumentException); 
            XmlNode node = document.CreateComment(text); 
            AddChild(node, write);
        } 

        public override void WriteProcessingInstruction(string name, string text) {
            VerifyState(Method.WriteProcessingInstruction);
            XmlConvert.VerifyCharData(text, ExceptionType.ArgumentException); 
            XmlNode node = document.CreateProcessingInstruction(name, text);
            AddChild(node, write); 
        } 

        public override void WriteEntityRef(string name) { 
            VerifyState(Method.WriteEntityRef);
            XmlNode node = document.CreateEntityReference(name);
            AddChild(node, write);
            // 
        }
 
        public override void WriteCharEntity(char ch) { 
            WriteString(new string(ch, 1));
        } 

        public override void WriteWhitespace(string text) {
            VerifyState(Method.WriteWhitespace);
            XmlConvert.VerifyCharData(text, ExceptionType.ArgumentException); 
            if (document.PreserveWhitespace) {
                XmlNode node = document.CreateWhitespace(text); 
                AddChild(node, write); 
            }
        } 

        public override void WriteString(string text) {
            VerifyState(Method.WriteString);
            XmlConvert.VerifyCharData(text, ExceptionType.ArgumentException); 
            XmlNode node = document.CreateTextNode(text);
            AddChild(node, write); 
        } 

        public override void WriteSurrogateCharEntity(char lowCh, char highCh) { 
            WriteString(new string(new char[] {highCh, lowCh}));
        }

        public override void WriteChars(char[] buffer, int index, int count) { 
            WriteString(new string(buffer, index, count));
        } 
 
        public override void WriteRaw(char[] buffer, int index, int count) {
            WriteString(new string(buffer, index, count)); 
        }

        public override void WriteRaw(string data) {
            WriteString(data); 
        }
 
        public override void Close() { 
            // nop
        } 

        internal override void Close(WriteState currentState) {
            if (currentState == WriteState.Error) {
                return; 
            }
            try { 
                switch (type) { 
                    case DocumentXmlWriterType.InsertSiblingAfter:
                        XmlNode parent = start.ParentNode; 
                        if (parent == null) {
                            throw new InvalidOperationException(Res.GetString(Res.Xpn_MissingParent));
                        }
                        for (int i = fragment.Count - 1; i >= 0; i--) { 
                            parent.InsertAfter(fragment[i], start);
                        } 
                        break; 
                    case DocumentXmlWriterType.InsertSiblingBefore:
                        parent = start.ParentNode; 
                        if (parent == null) {
                            throw new InvalidOperationException(Res.GetString(Res.Xpn_MissingParent));
                        }
                        for (int i = 0; i < fragment.Count; i++) { 
                            parent.InsertBefore(fragment[i], start);
                        } 
                        break; 
                    case DocumentXmlWriterType.PrependChild:
                        for (int i = fragment.Count - 1; i >= 0; i--) { 
                            start.PrependChild(fragment[i]);
                        }
                        break;
                    case DocumentXmlWriterType.AppendChild: 
                        for (int i = 0; i < fragment.Count; i++) {
                            start.AppendChild(fragment[i]); 
                        } 
                        break;
                    case DocumentXmlWriterType.AppendAttribute: 
                        CloseWithAppendAttribute();
                        break;
                    case DocumentXmlWriterType.ReplaceToFollowingSibling:
                        if (fragment.Count == 0) { 
                            throw new InvalidOperationException(Res.GetString(Res.Xpn_NoContent));
                        } 
                        CloseWithReplaceToFollowingSibling(); 
                        break;
                } 
            }
            finally {
                fragment.Clear();
            } 
        }
 
        private void CloseWithAppendAttribute() { 
            XmlElement elem = start as XmlElement;
            Debug.Assert(elem != null); 
            XmlAttributeCollection attrs = elem.Attributes;
            for (int i = 0; i < fragment.Count; i++) {
                XmlAttribute attr = fragment[i] as XmlAttribute;
                Debug.Assert(attr != null); 
                int offset = attrs.FindNodeOffsetNS(attr);
                if (offset != -1 
                    && ((XmlAttribute)attrs.Nodes[offset]).Specified) { 
                    throw new XmlException(Res.Xml_DupAttributeName, attr.Prefix.Length == 0 ? attr.LocalName : string.Concat(attr.Prefix, ":", attr.LocalName));
                } 
            }
            for (int i = 0; i < fragment.Count; i++) {
                XmlAttribute attr = fragment[i] as XmlAttribute;
                Debug.Assert(attr != null); 
                attrs.Append(attr);
            } 
        } 

        private void CloseWithReplaceToFollowingSibling() { 
            XmlNode parent = start.ParentNode;
            if (parent == null) {
                throw new InvalidOperationException(Res.GetString(Res.Xpn_MissingParent));
            } 
            if (start != end) {
                if (!DocumentXPathNavigator.IsFollowingSibling(start, end)) { 
                    throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition)); 
                }
                if (start.IsReadOnly) { 
                    throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Modify_ReadOnly));
                }
                DocumentXPathNavigator.DeleteToFollowingSibling(start.NextSibling, end);
            } 
            XmlNode fragment0 = fragment[0];
            parent.ReplaceChild(fragment0, start); 
            for (int i = fragment.Count - 1; i >= 1; i--) { 
                parent.InsertAfter(fragment[i], fragment0);
            } 
            navigator.ResetPosition(fragment0);
        }

        public override void Flush() { 
            // nop
        } 
 
        IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) {
            return namespaceManager.GetNamespacesInScope(scope); 
        }

        string IXmlNamespaceResolver.LookupNamespace(string prefix) {
            return namespaceManager.LookupNamespace(prefix); 
        }
 
        string IXmlNamespaceResolver.LookupPrefix(string namespaceName) { 
            return namespaceManager.LookupPrefix(namespaceName);
        } 

        void AddAttribute(XmlAttribute attr, XmlNode parent) {
            if (parent == null) {
                fragment.Add(attr); 
            }
            else { 
                XmlElement elem = parent as XmlElement; 
                if (elem == null) {
                    throw new InvalidOperationException(); 
                }
                elem.Attributes.Append(attr);
            }
        } 

        void AddChild(XmlNode node, XmlNode parent) { 
            if (parent == null) { 
                fragment.Add(node);
            } 
            else {
                parent.AppendChild(node);
            }
        } 

        State StartState() { 
            XmlNodeType nodeType = XmlNodeType.None; 

            switch (type) { 
                case DocumentXmlWriterType.InsertSiblingAfter:
                case DocumentXmlWriterType.InsertSiblingBefore:
                    XmlNode parent = start.ParentNode;
                    if (parent != null) { 
                        nodeType = parent.NodeType;
                    } 
                    if (nodeType == XmlNodeType.Document) { 
                        return State.Prolog;
                    } 
                    else if (nodeType == XmlNodeType.DocumentFragment)  {
                        return State.Fragment;
                    }
                    break; 
                case DocumentXmlWriterType.PrependChild:
                case DocumentXmlWriterType.AppendChild: 
                    nodeType = start.NodeType; 
                    if (nodeType == XmlNodeType.Document) {
                        return State.Prolog; 
                    }
                    else if (nodeType == XmlNodeType.DocumentFragment)  {
                        return State.Fragment;
                    } 
                    break;
                case DocumentXmlWriterType.AppendAttribute: 
                    return State.Attribute; 
                case DocumentXmlWriterType.ReplaceToFollowingSibling:
                    break; 
            }
            return State.Content;
        }
 
        static State[] changeState = {
//          State.Error,    State.Attribute,State.Prolog,   State.Fragment, State.Content, 
 
// Method.XmlDeclaration:
            State.Error,    State.Error,    State.Prolog,   State.Content,  State.Error, 
// Method.StartDocument:
            State.Error,    State.Error,    State.Error,    State.Error,    State.Error,
// Method.EndDocument:
            State.Error,    State.Error,    State.Error,    State.Error,    State.Error, 
// Method.DocType:
            State.Error,    State.Error,    State.Prolog,   State.Error,    State.Error, 
// Method.StartElement: 
            State.Error,    State.Error,    State.Content,  State.Content,  State.Content,
// Method.EndElement: 
            State.Error,    State.Error,    State.Error,    State.Error,    State.Content,
// Method.FullEndElement:
            State.Error,    State.Error,    State.Error,    State.Error,    State.Content,
// Method.StartAttribute: 
            State.Error,    State.Content,  State.Error,    State.Error,    State.Content,
// Method.EndAttribute: 
            State.Error,    State.Error,    State.Error,    State.Error,    State.Content, 
// Method.NamespaceDeclaration:
            State.Error,    State.Content,  State.Error,    State.Error,    State.Content, 
// Method.CData:
            State.Error,    State.Error,    State.Error,    State.Content,  State.Content,
// Method.Comment:
            State.Error,    State.Error,    State.Prolog,   State.Content,  State.Content, 
// Method.ProcessingInstruction:
            State.Error,    State.Error,    State.Prolog,   State.Content,  State.Content, 
// Method.EntityRef: 
            State.Error,    State.Error,    State.Error,    State.Content,  State.Content,
// Method.Whitespace: 
            State.Error,    State.Error,    State.Prolog,   State.Content,  State.Content,
// Method.String:
            State.Error,    State.Error,    State.Error,    State.Content,  State.Content,
        }; 

        void VerifyState(Method method) { 
            state = changeState[(int)method * (int)State.Last + (int)state]; 
            if (state == State.Error) {
                throw new InvalidOperationException(Res.GetString(Res.Xml_ClosedOrError)); 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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