TraceXPathNavigator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / SMDiagnostics / System / ServiceModel / Diagnostics / TraceXPathNavigator.cs / 1305376 / TraceXPathNavigator.cs

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

namespace System.ServiceModel.Diagnostics 
{
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Xml;
    using System.Xml.XPath; 
    using System.Globalization;
    using System.Text;
    using System.IO;
 
    // We have to put something here so that when this item appears in the
    // debugger, ToString() isn't called. Calling ToString() can cause bad behavior. 
    [DebuggerDisplay("")] 
    class TraceXPathNavigator : XPathNavigator
    { 
        const int UnlimitedSize = -1;
        ElementNode root = null;
        TraceNode current = null;
        bool closed = false; 
        XPathNodeType state = XPathNodeType.Element;
        int maxSize; 
        long currentSize; 

        public TraceXPathNavigator(int maxSize) 
        {
            this.maxSize = maxSize;
            this.currentSize = 0;
        } 

        interface IMeasurable 
        { 
            int Size { get; }
        } 

        class TraceNode
        {
            protected TraceNode(XPathNodeType nodeType, ElementNode parent) 
            {
                this.nodeType = nodeType; 
                this.parent = parent; 
            }
 
            internal XPathNodeType NodeType
            {
                get { return this.nodeType; }
            } 

            XPathNodeType nodeType; 
            internal ElementNode parent; 
        }
 
        class CommentNode : TraceNode, IMeasurable
        {
            internal CommentNode(string text, ElementNode parent)
                : base(XPathNodeType.Comment, parent) 
            {
                this.nodeValue = text; 
            } 

            internal string nodeValue; 

            public int Size
            {
                get 
                {
                    return this.nodeValue.Length + 8; //  
                } 
            }
        } 

        class ElementNode : TraceNode, IMeasurable
        {
            int attributeIndex = 0; 
            int elementIndex = 0;
 
            internal string name; 
            internal string prefix;
            internal string xmlns; 
            internal List childNodes = new List();
            internal List attributes = new List();
            internal TextNode text;
            internal bool movedToText = false; 

            internal ElementNode(string name, string prefix, ElementNode parent, string xmlns) 
                : base(XPathNodeType.Element, parent) 
            {
                this.name = name; 
                this.prefix = prefix;
                this.xmlns = xmlns;
            }
 
            internal void Add(TraceNode node)
            { 
                this.childNodes.Add(node); 
            }
 
            //This method returns all subnodes with the given path of local names. Namespaces are ignored.
            //For all path elements but the last one, the first match is taken. For the last path element, all matches are returned.
            internal IEnumerable FindSubnodes(string[] headersPath)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert(null != headersPath, "Headers path should not be null"); 
                AssertUtility.DebugAssert(headersPath.Length > 0, "There should be more than one item in the headersPath array."); 
#pragma warning restore 618
 
                if (null == headersPath)
                {
                    throw new ArgumentNullException("headersPath");
                } 
                ElementNode node = this;
                if (String.CompareOrdinal(node.name, headersPath[0]) != 0) 
                { 
                    node = null;
                } 
                int i = 0;
                while (null != node && ++i < headersPath.Length)
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert(null != headersPath[i], "None of the elements in headersPath should be null.");
#pragma warning restore 618 
                    ElementNode subNode = null; 
                    if (null != node.childNodes)
                    { 
                        foreach (TraceNode child in node.childNodes)
                        {
                            if (child.NodeType == XPathNodeType.Element)
                            { 
                                ElementNode childNode = child as ElementNode;
                                if (null != childNode && 0 == String.CompareOrdinal(childNode.name, headersPath[i])) 
                                { 
                                    if (headersPath.Length == i + 1)
                                    { 
                                        yield return childNode;
                                    }
                                    else
                                    { 
                                        subNode = childNode;
                                        break; 
                                    } 
                                }
                            } 
                        }
                    }

                    node = subNode; 
                }
            } 
 
            internal TraceNode MoveToNext()
            { 
                TraceNode retval = null;
                if ((this.elementIndex + 1) < this.childNodes.Count)
                {
                    ++this.elementIndex; 
                    retval = this.childNodes[this.elementIndex];
                } 
                return retval; 
            }
 
            internal bool MoveToFirstAttribute()
            {
                this.attributeIndex = 0;
                return null != this.attributes && this.attributes.Count > 0; 
            }
 
            internal bool MoveToNextAttribute() 
            {
                bool retval = false; 
                if ((this.attributeIndex + 1) < this.attributes.Count)
                {
                    ++this.attributeIndex;
                    retval = true; 
                }
                return retval; 
            } 

            internal void Reset() 
            {
                this.attributeIndex = 0;
                this.elementIndex = 0;
                this.movedToText = false; 
                if (null != this.childNodes)
                { 
                    foreach (TraceNode node in this.childNodes) 
                    {
                        if (node.NodeType == XPathNodeType.Element) 
                        {
                            ElementNode child = node as ElementNode;
                            if (child != null)
                            { 
                                child.Reset();
                            } 
                        } 
                    }
                } 
            }

            internal AttributeNode CurrentAttribute
            { 
                get
                { 
                    return this.attributes[this.attributeIndex]; 
                }
            } 

            public int Size
            {
                get 
                {
                    int size = 2 * this.name.Length + 6; //upper bound  
                    if (!string.IsNullOrEmpty(this.prefix)) 
                    {
                        size += this.prefix.Length + 1; 
                    }
                    if (!string.IsNullOrEmpty(this.xmlns))
                    {
                        size += this.xmlns.Length + 9;  // xmlns="xmlns" 
                    }
                    return size; 
                } 
            }
        } 

        class AttributeNode : IMeasurable
        {
            internal AttributeNode(string name, string prefix, string value, string xmlns) 
            {
                this.name = name; 
                this.prefix = prefix; 
                this.nodeValue = value;
                this.xmlns = xmlns; 
            }

            internal string name;
            internal string nodeValue; 
            internal string prefix;
            internal string xmlns; 
 
            public int Size
            { 
                get
                {
                    int size = this.name.Length + this.nodeValue.Length + 5;
 
                    if (!string.IsNullOrEmpty(this.prefix))
                    { 
                        size += this.prefix.Length + 1; 
                    }
 
                    if (!string.IsNullOrEmpty(this.xmlns))
                    {
                        size += this.xmlns.Length + 9; //upper bound
                    } 

                    return size; 
                } 
            }
        } 

        class ProcessingInstructionNode : TraceNode, IMeasurable
        {
            internal ProcessingInstructionNode(string name, string text, ElementNode parent) 
                :
                base(XPathNodeType.ProcessingInstruction, parent) 
            { 
                this.name = name;
                this.text = text; 
            }

            internal string name;
            internal string text; 

            public int Size 
            { 
                get
                { 
                    return this.name.Length + this.text.Length + 12; //
                }
            }
        } 

        class TextNode : IMeasurable 
        { 
            internal TextNode(string value)
            { 
                this.nodeValue = value;
            }
            internal string nodeValue;
 
            public int Size
            { 
                get 
                {
                    return this.nodeValue.Length; 
                }
            }
        }
 
        internal void AddElement(string prefix, string name, string xmlns)
        { 
            if (this.closed) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618
                throw new InvalidOperationException();
            } 
            else
            { 
                ElementNode node = new ElementNode(name, prefix, this.CurrentElement, xmlns); 
                if (this.current == null)
                { 
                    this.VerifySize(node);
                    this.root = node;
                    this.current = this.root;
                } 
                else if (!this.closed)
                { 
                    this.VerifySize(node); 
                    this.CurrentElement.Add(node);
                    this.current = node; 
                }
            }
        }
 
        internal void AddProcessingInstruction(string name, string text)
        { 
            if (this.current == null) 
            {
                return; 
            }
            else
            {
                ProcessingInstructionNode node = new ProcessingInstructionNode(name, text, this.CurrentElement); 
                this.VerifySize(node);
                this.CurrentElement.Add(node); 
            } 
        }
 
        internal void AddText(string value)
        {
            if (this.closed)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Cannot add data to a closed document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            if (this.current == null)
            {
                return;
            } 
            else
            { 
                if (this.CurrentElement.text == null) 
                {
                    TextNode node = new TextNode(value); 
                    this.VerifySize(node);
                    this.CurrentElement.text = node;
                }
                else if (!string.IsNullOrEmpty(value)) 
                {
                    this.VerifySize(value); 
                    this.CurrentElement.text.nodeValue += value; 
                }
            } 
        }

        internal void AddAttribute(string name, string value, string xmlns, string prefix)
        { 
            if (this.closed)
            { 
#pragma warning disable 618 
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618 
                throw new InvalidOperationException();
            }
            if (this.current == null)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            AttributeNode node = new AttributeNode(name, prefix, value, xmlns);
            this.VerifySize(node);
            this.CurrentElement.attributes.Add(node);
        } 

        internal void AddComment(string text) 
        { 
            if (this.closed)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            if (this.current == null) 
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException();
            }
            CommentNode node = new CommentNode(text, this.CurrentElement); 
            this.VerifySize(node);
            this.CurrentElement.Add(node); 
        } 

        internal void CloseElement() 
        {
            if (this.closed)
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("The document is already closed.");
#pragma warning restore 618 
                throw new InvalidOperationException(); 
            }
            else 
            {
                this.current = this.CurrentElement.parent;
                if (this.current == null)
                { 
                    this.closed = true;
                } 
            } 
        }
 
        public override string BaseURI
        {
            get { return String.Empty; }
        } 

        public override XPathNavigator Clone() 
        { 
            return this;
        } 

        public override bool IsEmptyElement
        {
            get 
            {
                bool retval = true; 
                if (this.current != null) 
                {
                    retval = this.CurrentElement.text != null || this.CurrentElement.childNodes.Count > 0; 
                }
                return retval;
            }
        } 

        public override bool IsSamePosition(XPathNavigator other) 
        { 
            return false;
        } 

        [DebuggerDisplay("")]
        public override string LocalName
        { 
            get { return this.Name; }
        } 
 
        public override string LookupPrefix(string ns)
        { 
            return this.LookupPrefix(ns, this.CurrentElement);
        }

        string LookupPrefix(string ns, ElementNode node) 
        {
            string retval = null; 
            if (string.Compare(ns, node.xmlns, StringComparison.Ordinal) == 0) 
            {
                retval = node.prefix; 
            }
            else
            {
                foreach (AttributeNode attributeNode in node.attributes) 
                {
                    if (string.Compare("xmlns", attributeNode.prefix, StringComparison.Ordinal) == 0) 
                    { 
                        if (string.Compare(ns, attributeNode.nodeValue, StringComparison.Ordinal) == 0)
                        { 
                            retval = attributeNode.name;
                            break;
                        }
                    } 
                }
            } 
 
            if (string.IsNullOrEmpty(retval) && node.parent != null)
            { 
                retval = LookupPrefix(ns, node.parent);
            }
            return retval;
        } 

        public override bool MoveTo(XPathNavigator other) 
        { 
            return false;
        } 

        public override bool MoveToFirstAttribute()
        {
            if (this.current == null) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            bool retval = this.CurrentElement.MoveToFirstAttribute();
            if (retval)
            { 
                this.state = XPathNodeType.Attribute;
            } 
            return retval; 
        }
 
        public override bool MoveToFirstChild()
        {
            if (this.current == null)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            bool retval = false;
            if (null != this.CurrentElement.childNodes && this.CurrentElement.childNodes.Count > 0)
            {
                this.current = this.CurrentElement.childNodes[0]; 
                this.state = this.current.NodeType;
                retval = true; 
            } 
            else if ((null == this.CurrentElement.childNodes || this.CurrentElement.childNodes.Count == 0) && this.CurrentElement.text != null)
            { 
                this.state = XPathNodeType.Text;
                this.CurrentElement.movedToText = true;
                retval = true;
            } 
            return retval;
        } 
 
        public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
        { 
            return false;
        }

        public override bool MoveToId(string id) 
        {
            return false; 
        } 

        public override bool MoveToNext() 
        {
            if (this.current == null)
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                throw new InvalidOperationException(); 
            }
            bool retval = false; 
            if (this.state != XPathNodeType.Text)
            {
                ElementNode parent = this.current.parent;
                if (parent != null) 
                {
                    TraceNode temp = parent.MoveToNext(); 
                    if (temp == null && parent.text != null && !parent.movedToText) 
                    {
                        this.state = XPathNodeType.Text; 
                        parent.movedToText = true;
                        this.current = parent;
                        retval = true;
                    } 
                    else if (temp != null)
                    { 
                        this.state = temp.NodeType; 
                        retval = true;
                        this.current = temp; 
                    }
                }
            }
            return retval; 
        }
 
        public override bool MoveToNextAttribute() 
        {
            if (this.current == null) 
            {
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            bool retval = this.CurrentElement.MoveToNextAttribute(); 
            if (retval)
            { 
                this.state = XPathNodeType.Attribute;
            }
            return retval;
        } 

        public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope) 
        { 
            return false;
        } 

        public override bool MoveToParent()
        {
            if (this.current == null) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            bool retval = false;
            switch (this.state)
            { 
                case XPathNodeType.Comment:
                case XPathNodeType.Element: 
                case XPathNodeType.ProcessingInstruction: 
                    if (this.current.parent != null)
                    { 
                        this.current = this.current.parent;
                        this.state = this.current.NodeType;
                        retval = true;
                    } 
                    break;
                case XPathNodeType.Attribute: 
                    this.state = XPathNodeType.Element; 
                    retval = true;
                    break; 
                case XPathNodeType.Text:
                    this.state = XPathNodeType.Element;
                    retval = true;
                    break; 
                case XPathNodeType.Namespace:
                    this.state = XPathNodeType.Element; 
                    retval = true; 
                    break;
            } 
            return retval;
        }

        public override bool MoveToPrevious() 
        {
            return false; 
        } 

        public override void MoveToRoot() 
        {
            this.current = this.root;
            this.state = XPathNodeType.Element;
            this.root.Reset(); 
        }
 
        [DebuggerDisplay("")] 
        public override string Name
        { 
            get
            {
                string retval = String.Empty;
                if (this.current == null) 
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                } 
                else
                {
                    switch (this.state)
                    { 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.name; 
                            break; 
                        case XPathNodeType.Element:
                            retval = this.CurrentElement.name; 
                            break;
                        case XPathNodeType.ProcessingInstruction:
                            retval = this.CurrentProcessingInstruction.name;
                            break; 
                    }
                } 
                return retval; 
            }
        } 

        public override System.Xml.XmlNameTable NameTable
        {
            get { return null; } 
        }
 
        [DebuggerDisplay("")] 
        public override string NamespaceURI
        { 
            get
            {
                string retval = String.Empty;
                if (this.current == null) 
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                } 
                else
                {
                    switch (this.state)
                    { 
                        case XPathNodeType.Element:
                            retval = this.CurrentElement.xmlns; 
                            break; 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.xmlns; 
                            break;
                        case XPathNodeType.Namespace:
                            retval = null;
                            break; 
                    }
                } 
                return retval; 
            }
        } 

        [DebuggerDisplay("")]
        public override XPathNodeType NodeType
        { 
            get { return this.state; }
        } 
 
        [DebuggerDisplay("")]
        public override string Prefix 
        {
            get
            {
                string retval = String.Empty; 
                if (this.current == null)
                { 
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                }
                else
                {
                    switch (this.state) 
                    {
                        case XPathNodeType.Element: 
                            retval = this.CurrentElement.prefix; 
                            break;
                        case XPathNodeType.Attribute: 
                            retval = this.CurrentElement.CurrentAttribute.prefix;
                            break;
                        case XPathNodeType.Namespace:
                            retval = null; 
                            break;
                    } 
                } 
                return retval;
            } 
        }

        CommentNode CurrentComment
        { 
            get { return this.current as CommentNode; }
        } 
 
        ElementNode CurrentElement
        { 
            get { return this.current as ElementNode; }
        }

        ProcessingInstructionNode CurrentProcessingInstruction 
        {
            get { return this.current as ProcessingInstructionNode; } 
        } 

        [DebuggerDisplay("")] 
        public override string Value
        {
            get
            { 
                string retval = String.Empty;
                if (this.current == null) 
                { 
#pragma warning disable 618
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                }
                else
                { 
                    switch (this.state)
                    { 
                        case XPathNodeType.Text: 
                            retval = this.CurrentElement.text.nodeValue;
                            break; 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.nodeValue;
                            break;
                        case XPathNodeType.Comment: 
                            retval = this.CurrentComment.nodeValue;
                            break; 
                        case XPathNodeType.ProcessingInstruction: 
                            retval = this.CurrentProcessingInstruction.text;
                            break; 
                    }
                }
                return retval;
            } 
        }
 
        internal WriteState WriteState 
        {
            get 
            {
                WriteState retval = WriteState.Error;
                if (this.current == null)
                { 
                    retval = WriteState.Start;
                } 
                else if (this.closed) 
                {
                    retval = WriteState.Closed; 
                }
                else
                {
                    switch (this.state) 
                    {
                        case XPathNodeType.Attribute: 
                            retval = WriteState.Attribute; 
                            break;
                        case XPathNodeType.Element: 
                            retval = WriteState.Element;
                            break;
                        case XPathNodeType.Text:
                            retval = WriteState.Content; 
                            break;
                        case XPathNodeType.Comment: 
                            retval = WriteState.Content; 
                            break;
                    } 
                }
                return retval;
            }
        } 

        public override string ToString() 
        { 
            this.MoveToRoot();
            StringBuilder sb = new StringBuilder(); 
            EncodingFallbackAwareXmlTextWriter writer = new EncodingFallbackAwareXmlTextWriter(new StringWriter(sb, CultureInfo.CurrentCulture));
            writer.WriteNode(this, false);
            return sb.ToString();
        } 

        void VerifySize(IMeasurable node) 
        { 
            this.VerifySize(node.Size);
        } 

        void VerifySize(string node)
        {
            this.VerifySize(node.Length); 
        }
 
        void VerifySize(int nodeSize) 
        {
            if (this.maxSize != TraceXPathNavigator.UnlimitedSize) 
            {
                if (this.currentSize + nodeSize > this.maxSize)
                {
                    throw new PlainXmlWriter.MaxSizeExceededException(); 
                }
            } 
            this.currentSize += nodeSize; 
        }
 
        public void RemovePii(string[][] paths)
        {
#pragma warning disable 618
            AssertUtility.DebugAssert(null != paths, ""); 
#pragma warning restore 618
            if (paths == null) 
            { 
                throw new ArgumentNullException("paths");
            } 

            foreach (string[] path in paths)
            {
                RemovePii(path); 
            }
        } 
 
        public void RemovePii(string[] path)
        { 
            RemovePii(path, DiagnosticStrings.PiiList);
        }

        public void RemovePii(string[] headersPath, string[] piiList) 
        {
#pragma warning disable 618 
            AssertUtility.DebugAssert(null != this.root, ""); 
            if (this.root == null)
            { 
                throw new InvalidOperationException();
            }
            foreach (ElementNode node in this.root.FindSubnodes(headersPath))
            { 
                AssertUtility.DebugAssert(null != node, "");
                MaskSubnodes(node, piiList); 
            } 
        }
#pragma warning restore 618 

        static void MaskElement(ElementNode element)
        {
            if (null != element) 
            {
                element.childNodes.Clear(); 
                element.Add(new CommentNode("Removed", element)); 
                element.text = null;
                element.attributes = null; 
            }
        }

        static void MaskSubnodes(ElementNode element, string[] elementNames) 
        {
            MaskSubnodes(element, elementNames, false); 
        } 

        static void MaskSubnodes(ElementNode element, string[] elementNames, bool processNodeItself) 
        {
#pragma warning disable 618
            AssertUtility.DebugAssert(null != elementNames, "");
#pragma warning restore 618 
            if (elementNames == null)
            { 
                throw new ArgumentNullException("elementNames"); 
            }
 
            if (null != element)
            {
                bool recurse = true;
                if (processNodeItself) 
                {
                    foreach (string elementName in elementNames) 
                    { 
#pragma warning disable 618
                        AssertUtility.DebugAssert(!String.IsNullOrEmpty(elementName), ""); 
#pragma warning restore 618
                        if (0 == String.CompareOrdinal(elementName, element.name))
                        {
                            MaskElement(element); 
                            recurse = false;
                            break; 
                        } 
                    }
                } 
                if (recurse)
                {
                    if (null != element.childNodes)
                    { 
                        foreach (ElementNode subNode in element.childNodes)
                        { 
#pragma warning disable 618 
                            AssertUtility.DebugAssert(null != subNode, "");
#pragma warning restore 618 
                            MaskSubnodes(subNode, elementNames, true);
                        }
                    }
                } 
            }
        } 
    } 
}

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

namespace System.ServiceModel.Diagnostics 
{
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Xml;
    using System.Xml.XPath; 
    using System.Globalization;
    using System.Text;
    using System.IO;
 
    // We have to put something here so that when this item appears in the
    // debugger, ToString() isn't called. Calling ToString() can cause bad behavior. 
    [DebuggerDisplay("")] 
    class TraceXPathNavigator : XPathNavigator
    { 
        const int UnlimitedSize = -1;
        ElementNode root = null;
        TraceNode current = null;
        bool closed = false; 
        XPathNodeType state = XPathNodeType.Element;
        int maxSize; 
        long currentSize; 

        public TraceXPathNavigator(int maxSize) 
        {
            this.maxSize = maxSize;
            this.currentSize = 0;
        } 

        interface IMeasurable 
        { 
            int Size { get; }
        } 

        class TraceNode
        {
            protected TraceNode(XPathNodeType nodeType, ElementNode parent) 
            {
                this.nodeType = nodeType; 
                this.parent = parent; 
            }
 
            internal XPathNodeType NodeType
            {
                get { return this.nodeType; }
            } 

            XPathNodeType nodeType; 
            internal ElementNode parent; 
        }
 
        class CommentNode : TraceNode, IMeasurable
        {
            internal CommentNode(string text, ElementNode parent)
                : base(XPathNodeType.Comment, parent) 
            {
                this.nodeValue = text; 
            } 

            internal string nodeValue; 

            public int Size
            {
                get 
                {
                    return this.nodeValue.Length + 8; //  
                } 
            }
        } 

        class ElementNode : TraceNode, IMeasurable
        {
            int attributeIndex = 0; 
            int elementIndex = 0;
 
            internal string name; 
            internal string prefix;
            internal string xmlns; 
            internal List childNodes = new List();
            internal List attributes = new List();
            internal TextNode text;
            internal bool movedToText = false; 

            internal ElementNode(string name, string prefix, ElementNode parent, string xmlns) 
                : base(XPathNodeType.Element, parent) 
            {
                this.name = name; 
                this.prefix = prefix;
                this.xmlns = xmlns;
            }
 
            internal void Add(TraceNode node)
            { 
                this.childNodes.Add(node); 
            }
 
            //This method returns all subnodes with the given path of local names. Namespaces are ignored.
            //For all path elements but the last one, the first match is taken. For the last path element, all matches are returned.
            internal IEnumerable FindSubnodes(string[] headersPath)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert(null != headersPath, "Headers path should not be null"); 
                AssertUtility.DebugAssert(headersPath.Length > 0, "There should be more than one item in the headersPath array."); 
#pragma warning restore 618
 
                if (null == headersPath)
                {
                    throw new ArgumentNullException("headersPath");
                } 
                ElementNode node = this;
                if (String.CompareOrdinal(node.name, headersPath[0]) != 0) 
                { 
                    node = null;
                } 
                int i = 0;
                while (null != node && ++i < headersPath.Length)
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert(null != headersPath[i], "None of the elements in headersPath should be null.");
#pragma warning restore 618 
                    ElementNode subNode = null; 
                    if (null != node.childNodes)
                    { 
                        foreach (TraceNode child in node.childNodes)
                        {
                            if (child.NodeType == XPathNodeType.Element)
                            { 
                                ElementNode childNode = child as ElementNode;
                                if (null != childNode && 0 == String.CompareOrdinal(childNode.name, headersPath[i])) 
                                { 
                                    if (headersPath.Length == i + 1)
                                    { 
                                        yield return childNode;
                                    }
                                    else
                                    { 
                                        subNode = childNode;
                                        break; 
                                    } 
                                }
                            } 
                        }
                    }

                    node = subNode; 
                }
            } 
 
            internal TraceNode MoveToNext()
            { 
                TraceNode retval = null;
                if ((this.elementIndex + 1) < this.childNodes.Count)
                {
                    ++this.elementIndex; 
                    retval = this.childNodes[this.elementIndex];
                } 
                return retval; 
            }
 
            internal bool MoveToFirstAttribute()
            {
                this.attributeIndex = 0;
                return null != this.attributes && this.attributes.Count > 0; 
            }
 
            internal bool MoveToNextAttribute() 
            {
                bool retval = false; 
                if ((this.attributeIndex + 1) < this.attributes.Count)
                {
                    ++this.attributeIndex;
                    retval = true; 
                }
                return retval; 
            } 

            internal void Reset() 
            {
                this.attributeIndex = 0;
                this.elementIndex = 0;
                this.movedToText = false; 
                if (null != this.childNodes)
                { 
                    foreach (TraceNode node in this.childNodes) 
                    {
                        if (node.NodeType == XPathNodeType.Element) 
                        {
                            ElementNode child = node as ElementNode;
                            if (child != null)
                            { 
                                child.Reset();
                            } 
                        } 
                    }
                } 
            }

            internal AttributeNode CurrentAttribute
            { 
                get
                { 
                    return this.attributes[this.attributeIndex]; 
                }
            } 

            public int Size
            {
                get 
                {
                    int size = 2 * this.name.Length + 6; //upper bound  
                    if (!string.IsNullOrEmpty(this.prefix)) 
                    {
                        size += this.prefix.Length + 1; 
                    }
                    if (!string.IsNullOrEmpty(this.xmlns))
                    {
                        size += this.xmlns.Length + 9;  // xmlns="xmlns" 
                    }
                    return size; 
                } 
            }
        } 

        class AttributeNode : IMeasurable
        {
            internal AttributeNode(string name, string prefix, string value, string xmlns) 
            {
                this.name = name; 
                this.prefix = prefix; 
                this.nodeValue = value;
                this.xmlns = xmlns; 
            }

            internal string name;
            internal string nodeValue; 
            internal string prefix;
            internal string xmlns; 
 
            public int Size
            { 
                get
                {
                    int size = this.name.Length + this.nodeValue.Length + 5;
 
                    if (!string.IsNullOrEmpty(this.prefix))
                    { 
                        size += this.prefix.Length + 1; 
                    }
 
                    if (!string.IsNullOrEmpty(this.xmlns))
                    {
                        size += this.xmlns.Length + 9; //upper bound
                    } 

                    return size; 
                } 
            }
        } 

        class ProcessingInstructionNode : TraceNode, IMeasurable
        {
            internal ProcessingInstructionNode(string name, string text, ElementNode parent) 
                :
                base(XPathNodeType.ProcessingInstruction, parent) 
            { 
                this.name = name;
                this.text = text; 
            }

            internal string name;
            internal string text; 

            public int Size 
            { 
                get
                { 
                    return this.name.Length + this.text.Length + 12; //
                }
            }
        } 

        class TextNode : IMeasurable 
        { 
            internal TextNode(string value)
            { 
                this.nodeValue = value;
            }
            internal string nodeValue;
 
            public int Size
            { 
                get 
                {
                    return this.nodeValue.Length; 
                }
            }
        }
 
        internal void AddElement(string prefix, string name, string xmlns)
        { 
            if (this.closed) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618
                throw new InvalidOperationException();
            } 
            else
            { 
                ElementNode node = new ElementNode(name, prefix, this.CurrentElement, xmlns); 
                if (this.current == null)
                { 
                    this.VerifySize(node);
                    this.root = node;
                    this.current = this.root;
                } 
                else if (!this.closed)
                { 
                    this.VerifySize(node); 
                    this.CurrentElement.Add(node);
                    this.current = node; 
                }
            }
        }
 
        internal void AddProcessingInstruction(string name, string text)
        { 
            if (this.current == null) 
            {
                return; 
            }
            else
            {
                ProcessingInstructionNode node = new ProcessingInstructionNode(name, text, this.CurrentElement); 
                this.VerifySize(node);
                this.CurrentElement.Add(node); 
            } 
        }
 
        internal void AddText(string value)
        {
            if (this.closed)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Cannot add data to a closed document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            if (this.current == null)
            {
                return;
            } 
            else
            { 
                if (this.CurrentElement.text == null) 
                {
                    TextNode node = new TextNode(value); 
                    this.VerifySize(node);
                    this.CurrentElement.text = node;
                }
                else if (!string.IsNullOrEmpty(value)) 
                {
                    this.VerifySize(value); 
                    this.CurrentElement.text.nodeValue += value; 
                }
            } 
        }

        internal void AddAttribute(string name, string value, string xmlns, string prefix)
        { 
            if (this.closed)
            { 
#pragma warning disable 618 
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618 
                throw new InvalidOperationException();
            }
            if (this.current == null)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            AttributeNode node = new AttributeNode(name, prefix, value, xmlns);
            this.VerifySize(node);
            this.CurrentElement.attributes.Add(node);
        } 

        internal void AddComment(string text) 
        { 
            if (this.closed)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Cannot add data to a closed document");
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            if (this.current == null) 
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException();
            }
            CommentNode node = new CommentNode(text, this.CurrentElement); 
            this.VerifySize(node);
            this.CurrentElement.Add(node); 
        } 

        internal void CloseElement() 
        {
            if (this.closed)
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("The document is already closed.");
#pragma warning restore 618 
                throw new InvalidOperationException(); 
            }
            else 
            {
                this.current = this.CurrentElement.parent;
                if (this.current == null)
                { 
                    this.closed = true;
                } 
            } 
        }
 
        public override string BaseURI
        {
            get { return String.Empty; }
        } 

        public override XPathNavigator Clone() 
        { 
            return this;
        } 

        public override bool IsEmptyElement
        {
            get 
            {
                bool retval = true; 
                if (this.current != null) 
                {
                    retval = this.CurrentElement.text != null || this.CurrentElement.childNodes.Count > 0; 
                }
                return retval;
            }
        } 

        public override bool IsSamePosition(XPathNavigator other) 
        { 
            return false;
        } 

        [DebuggerDisplay("")]
        public override string LocalName
        { 
            get { return this.Name; }
        } 
 
        public override string LookupPrefix(string ns)
        { 
            return this.LookupPrefix(ns, this.CurrentElement);
        }

        string LookupPrefix(string ns, ElementNode node) 
        {
            string retval = null; 
            if (string.Compare(ns, node.xmlns, StringComparison.Ordinal) == 0) 
            {
                retval = node.prefix; 
            }
            else
            {
                foreach (AttributeNode attributeNode in node.attributes) 
                {
                    if (string.Compare("xmlns", attributeNode.prefix, StringComparison.Ordinal) == 0) 
                    { 
                        if (string.Compare(ns, attributeNode.nodeValue, StringComparison.Ordinal) == 0)
                        { 
                            retval = attributeNode.name;
                            break;
                        }
                    } 
                }
            } 
 
            if (string.IsNullOrEmpty(retval) && node.parent != null)
            { 
                retval = LookupPrefix(ns, node.parent);
            }
            return retval;
        } 

        public override bool MoveTo(XPathNavigator other) 
        { 
            return false;
        } 

        public override bool MoveToFirstAttribute()
        {
            if (this.current == null) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            bool retval = this.CurrentElement.MoveToFirstAttribute();
            if (retval)
            { 
                this.state = XPathNodeType.Attribute;
            } 
            return retval; 
        }
 
        public override bool MoveToFirstChild()
        {
            if (this.current == null)
            { 
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            bool retval = false;
            if (null != this.CurrentElement.childNodes && this.CurrentElement.childNodes.Count > 0)
            {
                this.current = this.CurrentElement.childNodes[0]; 
                this.state = this.current.NodeType;
                retval = true; 
            } 
            else if ((null == this.CurrentElement.childNodes || this.CurrentElement.childNodes.Count == 0) && this.CurrentElement.text != null)
            { 
                this.state = XPathNodeType.Text;
                this.CurrentElement.movedToText = true;
                retval = true;
            } 
            return retval;
        } 
 
        public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
        { 
            return false;
        }

        public override bool MoveToId(string id) 
        {
            return false; 
        } 

        public override bool MoveToNext() 
        {
            if (this.current == null)
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                throw new InvalidOperationException(); 
            }
            bool retval = false; 
            if (this.state != XPathNodeType.Text)
            {
                ElementNode parent = this.current.parent;
                if (parent != null) 
                {
                    TraceNode temp = parent.MoveToNext(); 
                    if (temp == null && parent.text != null && !parent.movedToText) 
                    {
                        this.state = XPathNodeType.Text; 
                        parent.movedToText = true;
                        this.current = parent;
                        retval = true;
                    } 
                    else if (temp != null)
                    { 
                        this.state = temp.NodeType; 
                        retval = true;
                        this.current = temp; 
                    }
                }
            }
            return retval; 
        }
 
        public override bool MoveToNextAttribute() 
        {
            if (this.current == null) 
            {
#pragma warning disable 618
                AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                throw new InvalidOperationException();
            } 
            bool retval = this.CurrentElement.MoveToNextAttribute(); 
            if (retval)
            { 
                this.state = XPathNodeType.Attribute;
            }
            return retval;
        } 

        public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope) 
        { 
            return false;
        } 

        public override bool MoveToParent()
        {
            if (this.current == null) 
            {
#pragma warning disable 618 
                AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                throw new InvalidOperationException(); 
            }
            bool retval = false;
            switch (this.state)
            { 
                case XPathNodeType.Comment:
                case XPathNodeType.Element: 
                case XPathNodeType.ProcessingInstruction: 
                    if (this.current.parent != null)
                    { 
                        this.current = this.current.parent;
                        this.state = this.current.NodeType;
                        retval = true;
                    } 
                    break;
                case XPathNodeType.Attribute: 
                    this.state = XPathNodeType.Element; 
                    retval = true;
                    break; 
                case XPathNodeType.Text:
                    this.state = XPathNodeType.Element;
                    retval = true;
                    break; 
                case XPathNodeType.Namespace:
                    this.state = XPathNodeType.Element; 
                    retval = true; 
                    break;
            } 
            return retval;
        }

        public override bool MoveToPrevious() 
        {
            return false; 
        } 

        public override void MoveToRoot() 
        {
            this.current = this.root;
            this.state = XPathNodeType.Element;
            this.root.Reset(); 
        }
 
        [DebuggerDisplay("")] 
        public override string Name
        { 
            get
            {
                string retval = String.Empty;
                if (this.current == null) 
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                } 
                else
                {
                    switch (this.state)
                    { 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.name; 
                            break; 
                        case XPathNodeType.Element:
                            retval = this.CurrentElement.name; 
                            break;
                        case XPathNodeType.ProcessingInstruction:
                            retval = this.CurrentProcessingInstruction.name;
                            break; 
                    }
                } 
                return retval; 
            }
        } 

        public override System.Xml.XmlNameTable NameTable
        {
            get { return null; } 
        }
 
        [DebuggerDisplay("")] 
        public override string NamespaceURI
        { 
            get
            {
                string retval = String.Empty;
                if (this.current == null) 
                {
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                } 
                else
                {
                    switch (this.state)
                    { 
                        case XPathNodeType.Element:
                            retval = this.CurrentElement.xmlns; 
                            break; 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.xmlns; 
                            break;
                        case XPathNodeType.Namespace:
                            retval = null;
                            break; 
                    }
                } 
                return retval; 
            }
        } 

        [DebuggerDisplay("")]
        public override XPathNodeType NodeType
        { 
            get { return this.state; }
        } 
 
        [DebuggerDisplay("")]
        public override string Prefix 
        {
            get
            {
                string retval = String.Empty; 
                if (this.current == null)
                { 
#pragma warning disable 618 
                    AssertUtility.DebugAssert("Operation is invalid on an empty document");
#pragma warning restore 618 
                }
                else
                {
                    switch (this.state) 
                    {
                        case XPathNodeType.Element: 
                            retval = this.CurrentElement.prefix; 
                            break;
                        case XPathNodeType.Attribute: 
                            retval = this.CurrentElement.CurrentAttribute.prefix;
                            break;
                        case XPathNodeType.Namespace:
                            retval = null; 
                            break;
                    } 
                } 
                return retval;
            } 
        }

        CommentNode CurrentComment
        { 
            get { return this.current as CommentNode; }
        } 
 
        ElementNode CurrentElement
        { 
            get { return this.current as ElementNode; }
        }

        ProcessingInstructionNode CurrentProcessingInstruction 
        {
            get { return this.current as ProcessingInstructionNode; } 
        } 

        [DebuggerDisplay("")] 
        public override string Value
        {
            get
            { 
                string retval = String.Empty;
                if (this.current == null) 
                { 
#pragma warning disable 618
                    AssertUtility.DebugAssert("Operation is invalid on an empty document"); 
#pragma warning restore 618
                }
                else
                { 
                    switch (this.state)
                    { 
                        case XPathNodeType.Text: 
                            retval = this.CurrentElement.text.nodeValue;
                            break; 
                        case XPathNodeType.Attribute:
                            retval = this.CurrentElement.CurrentAttribute.nodeValue;
                            break;
                        case XPathNodeType.Comment: 
                            retval = this.CurrentComment.nodeValue;
                            break; 
                        case XPathNodeType.ProcessingInstruction: 
                            retval = this.CurrentProcessingInstruction.text;
                            break; 
                    }
                }
                return retval;
            } 
        }
 
        internal WriteState WriteState 
        {
            get 
            {
                WriteState retval = WriteState.Error;
                if (this.current == null)
                { 
                    retval = WriteState.Start;
                } 
                else if (this.closed) 
                {
                    retval = WriteState.Closed; 
                }
                else
                {
                    switch (this.state) 
                    {
                        case XPathNodeType.Attribute: 
                            retval = WriteState.Attribute; 
                            break;
                        case XPathNodeType.Element: 
                            retval = WriteState.Element;
                            break;
                        case XPathNodeType.Text:
                            retval = WriteState.Content; 
                            break;
                        case XPathNodeType.Comment: 
                            retval = WriteState.Content; 
                            break;
                    } 
                }
                return retval;
            }
        } 

        public override string ToString() 
        { 
            this.MoveToRoot();
            StringBuilder sb = new StringBuilder(); 
            EncodingFallbackAwareXmlTextWriter writer = new EncodingFallbackAwareXmlTextWriter(new StringWriter(sb, CultureInfo.CurrentCulture));
            writer.WriteNode(this, false);
            return sb.ToString();
        } 

        void VerifySize(IMeasurable node) 
        { 
            this.VerifySize(node.Size);
        } 

        void VerifySize(string node)
        {
            this.VerifySize(node.Length); 
        }
 
        void VerifySize(int nodeSize) 
        {
            if (this.maxSize != TraceXPathNavigator.UnlimitedSize) 
            {
                if (this.currentSize + nodeSize > this.maxSize)
                {
                    throw new PlainXmlWriter.MaxSizeExceededException(); 
                }
            } 
            this.currentSize += nodeSize; 
        }
 
        public void RemovePii(string[][] paths)
        {
#pragma warning disable 618
            AssertUtility.DebugAssert(null != paths, ""); 
#pragma warning restore 618
            if (paths == null) 
            { 
                throw new ArgumentNullException("paths");
            } 

            foreach (string[] path in paths)
            {
                RemovePii(path); 
            }
        } 
 
        public void RemovePii(string[] path)
        { 
            RemovePii(path, DiagnosticStrings.PiiList);
        }

        public void RemovePii(string[] headersPath, string[] piiList) 
        {
#pragma warning disable 618 
            AssertUtility.DebugAssert(null != this.root, ""); 
            if (this.root == null)
            { 
                throw new InvalidOperationException();
            }
            foreach (ElementNode node in this.root.FindSubnodes(headersPath))
            { 
                AssertUtility.DebugAssert(null != node, "");
                MaskSubnodes(node, piiList); 
            } 
        }
#pragma warning restore 618 

        static void MaskElement(ElementNode element)
        {
            if (null != element) 
            {
                element.childNodes.Clear(); 
                element.Add(new CommentNode("Removed", element)); 
                element.text = null;
                element.attributes = null; 
            }
        }

        static void MaskSubnodes(ElementNode element, string[] elementNames) 
        {
            MaskSubnodes(element, elementNames, false); 
        } 

        static void MaskSubnodes(ElementNode element, string[] elementNames, bool processNodeItself) 
        {
#pragma warning disable 618
            AssertUtility.DebugAssert(null != elementNames, "");
#pragma warning restore 618 
            if (elementNames == null)
            { 
                throw new ArgumentNullException("elementNames"); 
            }
 
            if (null != element)
            {
                bool recurse = true;
                if (processNodeItself) 
                {
                    foreach (string elementName in elementNames) 
                    { 
#pragma warning disable 618
                        AssertUtility.DebugAssert(!String.IsNullOrEmpty(elementName), ""); 
#pragma warning restore 618
                        if (0 == String.CompareOrdinal(elementName, element.name))
                        {
                            MaskElement(element); 
                            recurse = false;
                            break; 
                        } 
                    }
                } 
                if (recurse)
                {
                    if (null != element.childNodes)
                    { 
                        foreach (ElementNode subNode in element.childNodes)
                        { 
#pragma warning disable 618 
                            AssertUtility.DebugAssert(null != subNode, "");
#pragma warning restore 618 
                            MaskSubnodes(subNode, elementNames, true);
                        }
                    }
                } 
            }
        } 
    } 
}

// 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