XLinq.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / XLinq / System / Xml / Linq / XLinq.cs / 3 / XLinq.cs

                            using System; 
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; 
using System.IO;
using System.Linq; 
using System.Runtime.Serialization; 
using System.Text;
using System.Threading; 
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using CultureInfo = System.Globalization.CultureInfo; 

[module:SuppressMessage("Microsoft.Performance","CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xml.Linq.Res.#GetObject(System.String)", Justification="Build generated code.")] 
[module:SuppressMessage("Microsoft.Performance","CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xml.Linq.Res.#get_Resources()", Justification="Build generated code.")] 

namespace System.Xml.Linq 
{
    /// 
    /// Represents a name of an XML element or attribute. This class cannot be inherited.
    ///  
    [Serializable()]
    [SuppressMessage("Microsoft.Usage", "CA2229:ImplementSerializationConstructors", Justification = "Deserialization handled by NameSerializer.")] 
    public sealed class XName : IEquatable, ISerializable 
    {
        XNamespace ns; 
        string localName;
        int hashCode;

        ///  
        /// Constructor, internal so that external users must go through the Get() method to create an XName.
        ///  
        internal XName(XNamespace ns, string localName) { 
            this.ns = ns;
            this.localName = XmlConvert.VerifyNCName(localName); 
            this.hashCode = ns.GetHashCode() ^ localName.GetHashCode();
        }

        ///  
        /// Gets the local (unqualified) part of the name.
        ///  
        ///  
        public string LocalName {
            get { return localName; } 
        }

        /// 
        /// Gets the namespace of the name. 
        /// 
        public XNamespace Namespace { 
            get { return ns; } 
        }
 
        /// 
        /// Gets the namespace name part of the name.
        /// 
        public string NamespaceName { 
            get { return ns.NamespaceName; }
        } 
 
        /// 
        /// Returns the expanded XML name in the format: {namespaceName}localName. 
        /// 
        public override string ToString() {
            if (ns.NamespaceName.Length == 0) return localName;
            return "{" + ns.NamespaceName + "}" + localName; 
        }
 
        ///  
        /// Returns an  object created from the specified expanded name.
        ///  
        /// 
        /// A string containing an expanded XML name in the format: {namespace}localname.
        /// 
        ///  
        /// An  object constructed from the specified expanded name.
        ///  
        public static XName Get(string expandedName) { 
            if (expandedName == null) throw new ArgumentNullException("expandedName");
            if (expandedName.Length == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidExpandedName, expandedName)); 
            if (expandedName[0] == '{') {
                int i = expandedName.LastIndexOf('}');
                if (i <= 1 || i == expandedName.Length - 1) throw new ArgumentException(Res.GetString(Res.Argument_InvalidExpandedName, expandedName));
                return XNamespace.Get(expandedName, 1, i - 1).GetName(expandedName, i + 1, expandedName.Length - i - 1); 
            }
            else { 
                return XNamespace.None.GetName(expandedName); 
            }
        } 

        /// 
        /// Returns an  object from a local name and a namespace.
        ///  
        /// A local (unqualified) name.
        /// An XML namespace. 
        /// An XName object created from the specified local name and namespace. 
        public static XName Get(string localName, string namespaceName) {
            return XNamespace.Get(namespaceName).GetName(localName); 
        }

        /// 
        /// Converts a string formatted as an expanded XML name ({namespace}localname) to an XName object. 
        /// 
        /// A string containing an expanded XML name in the format: {namespace}localname. 
        /// An XName object constructed from the expanded name. 
        [CLSCompliant(false)]
        public static implicit operator XName(string expandedName) { 
            return expandedName != null ? Get(expandedName) : null;
        }

        ///  
        /// Determines whether the specified  is equal to the current .
        ///  
        /// The XName to compare to the current XName. 
        /// 
        /// true if the specified  is equal to the current XName; otherwise false. 
        /// 
        /// 
        /// For two  objects to be equal, they must have the same expanded name.
        ///  
        public override bool Equals(object obj) {
            return (object)this == obj; 
        } 

        ///  
        /// Serves as a hash function for . GetHashCode is suitable
        /// for use in hashing algorithms and data structures like a hash table.
        /// 
        public override int GetHashCode() { 
            return hashCode;
        } 
 
        // The overloads of == and != are included to enable comparisons between
        // XName and string (e.g. element.Name == "foo"). C#'s predefined reference 
        // equality operators require one operand to be convertible to the type of
        // the other through reference conversions only and do not consider the
        // implicit conversion from string to XName.
 
        /// 
        /// Returns a value indicating whether two instances of  are equal. 
        ///  
        /// The first XName to compare.
        /// The second XName to compare. 
        /// true if left and right are equal; otherwise false.
        /// 
        /// This overload is included to enable the comparison between
        /// an instance of XName and string. 
        /// 
        public static bool operator ==(XName left, XName right) { 
            return (object)left == (object)right; 
        }
 
        /// 
        /// Returns a value indicating whether two instances of  are not equal.
        /// 
        /// The first XName to compare. 
        /// The second XName to compare.
        /// true if left and right are not equal; otherwise false. 
        ///  
        /// This overload is included to enable the comparison between
        /// an instance of XName and string. 
        /// 
        public static bool operator !=(XName left, XName right) {
            return (object)left != (object)right;
        } 

        ///  
        /// Indicates whether the current  is equal to 
        /// the specified 
        ///  
        /// The  to compare with the
        /// current 
        /// 
        /// Returns true if the current  is equal to 
        /// the specified . Returns false otherwise.
        ///  
        bool IEquatable.Equals(XName other) { 
            return (object)this == (object)other;
        } 

        /// 
        /// Populates a  with the data needed to
        /// serialize the  
        /// 
        /// The  to populate with data 
        /// The destination for this serialization 
        [System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityAction.LinkDemand, 
            Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
            if (info == null) throw new ArgumentNullException("info");
            info.AddValue("name", ToString()); 
            info.SetType(typeof(NameSerializer));
        } 
    } 

    [Serializable()] 
    internal sealed class NameSerializer : IObjectReference, ISerializable
    {
        string expandedName;
 
        private NameSerializer(SerializationInfo info, StreamingContext context) {
            if (info == null) throw new ArgumentNullException("info"); 
            expandedName = info.GetString("name"); 
        }
 
        object IObjectReference.GetRealObject(StreamingContext context) {
            return XName.Get(expandedName);
        }
 
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
            throw new NotSupportedException(); // nop 
        } 
    }
 
    /// 
    /// Represents an XML namespace. This class cannot be inherited.
    /// 
    public sealed class XNamespace 
    {
        internal const string xmlPrefixNamespace = "http://www.w3.org/XML/1998/namespace"; 
        internal const string xmlnsPrefixNamespace = "http://www.w3.org/2000/xmlns/"; 

        static XHashtable namespaces; 
        static WeakReference refNone;
        static WeakReference refXml;
        static WeakReference refXmlns;
 
        string namespaceName;
        int hashCode; 
        XHashtable names; 

        const int NamesCapacity = 8;           // Starting capacity of XName table, which must be power of 2 
        const int NamespacesCapacity = 32;     // Starting capacity of XNamespace table, which must be power of 2

        /// 
        /// Constructor, internal so that external users must go through the Get() method to create an XNamespace. 
        /// 
        internal XNamespace(string namespaceName) { 
            this.namespaceName = namespaceName; 
            this.hashCode = namespaceName.GetHashCode();
            names = new XHashtable(ExtractLocalName, NamesCapacity); 
        }

        /// 
        /// Gets the namespace name of the namespace. 
        /// 
        public string NamespaceName { 
            get { return namespaceName; } 
        }
 
        /// 
        /// Returns an XName object created from the current instance and the specified local name.
        /// 
        ///  
        /// The returned XName object is guaranteed to be atomic (i.e. the only one in the system for this
        /// particular expanded name). 
        ///  
        public XName GetName(string localName) {
            if (localName == null) throw new ArgumentNullException("localName"); 
            return GetName(localName, 0, localName.Length);
        }

        ///  
        /// Returns the namespace name of this .
        ///  
        /// A string value containing the namespace name. 
        public override string ToString() {
            return namespaceName; 
        }

        /// 
        /// Gets the XNamespace object that corresponds to no namespace. 
        /// 
        ///  
        /// If an element or attribute is in no namespace, its namespace 
        /// will be set to the namespace returned by this property.
        ///  
        public static XNamespace None {
            get {
                return EnsureNamespace(ref refNone, string.Empty);
            } 
        }
 
        ///  
        /// Gets the XNamespace object that corresponds to the xml uri (http://www.w3.org/XML/1998/namespace).
        ///  
        public static XNamespace Xml {
            get {
                return EnsureNamespace(ref refXml, xmlPrefixNamespace);
            } 
        }
 
        ///  
        /// Gets the XNamespace object that corresponds to the xmlns uri (http://www.w3.org/2000/xmlns/).
        ///  
        public static XNamespace Xmlns {
            get {
                return EnsureNamespace(ref refXmlns, xmlnsPrefixNamespace);
            } 
        }
 
        ///  
        /// Gets an XNamespace created from the specified namespace name.
        ///  
        /// 
        /// The returned XNamespace object is guaranteed to be atomic
        /// (i.e. the only one in the system for that particular namespace name).
        ///  
        public static XNamespace Get(string namespaceName) {
            if (namespaceName == null) throw new ArgumentNullException("namespaceName"); 
            return Get(namespaceName, 0, namespaceName.Length); 
        }
 
        /// 
        /// Converts a string containing a namespace name to an XNamespace.
        /// 
        /// A string containing the namespace name. 
        /// An XNamespace constructed from the namespace name string.
        [CLSCompliant(false)] 
        public static implicit operator XNamespace(string namespaceName) { 
            return namespaceName != null ? Get(namespaceName) : null;
        } 

        /// 
        /// Combines an  object with a local name to create an .
        ///  
        /// The namespace for the expanded name.
        /// The local name for the expanded name. 
        /// The new XName constructed from the namespace and local name. 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Functionality available via XNamespace.Get().")]
        public static XName operator +(XNamespace ns, string localName) { 
            if (ns == null) throw new ArgumentNullException("ns");
            return ns.GetName(localName);
        }
 
        /// 
        /// Determines whether the specified  is equal to the current . 
        ///  
        /// The XNamespace to compare to the current XNamespace.
        ///  
        /// true if the specified  is equal to the current XNamespace; otherwise false.
        /// 
        /// 
        /// For two  objects to be equal they must have the same 
        /// namespace name.
        ///  
        public override bool Equals(object obj) { 
            return (object)this == obj;
        } 

        /// 
        /// Serves as a hash function for . GetHashCode is suitable
        /// for use in hashing algorithms and data structures like a hash table. 
        /// 
        public override int GetHashCode() { 
            return hashCode; 
        }
 

        // The overloads of == and != are included to enable comparisons between
        // XNamespace and string (e.g. element.Name.Namespace == "foo"). C#'s
        // predefined reference equality operators require one operand to be 
        // convertible to the type of the other through reference conversions only
        // and do not consider the implicit conversion from string to XNamespace. 
 
        /// 
        /// Returns a value indicating whether two instances of  are equal. 
        /// 
        /// The first XNamespace to compare.
        /// The second XNamespace to compare.
        /// true if left and right are equal; otherwise false. 
        /// 
        /// This overload is included to enable the comparison between 
        /// an instance of XNamespace and string. 
        /// 
        public static bool operator ==(XNamespace left, XNamespace right) { 
            return (object)left == (object)right;
        }

        ///  
        /// Returns a value indicating whether two instances of  are not equal.
        ///  
        /// The first XNamespace to compare. 
        /// The second XNamespace to compare.
        /// true if left and right are not equal; otherwise false. 
        /// 
        /// This overload is included to enable the comparison between
        /// an instance of XNamespace and string.
        ///  
        public static bool operator !=(XNamespace left, XNamespace right) {
            return (object)left != (object)right; 
        } 

        ///  
        /// Returns an  created from this XNamespace  and a portion of the passed in
        /// local name parameter.  The returned XName object is guaranteed to be atomic (i.e. the only one in the system for
        /// this particular expanded name).
        ///  
        internal XName GetName(string localName, int index, int count) {
            Debug.Assert(index >= 0 && index <= localName.Length, "Caller should have checked that index was in bounds"); 
            Debug.Assert(count >= 0 && index + count <= localName.Length, "Caller should have checked that count was in bounds"); 

            // Attempt to get the local name from the hash table 
            XName name;
            if (names.TryGetValue(localName, index, count, out name))
                return name;
 
            // No local name has yet been added, so add it now
            return names.Add(new XName(this, localName.Substring(index, count))); 
        } 

        ///  
        /// Returns an  created from a portion of the passed in namespace name parameter.  The returned XNamespace
        /// object is guaranteed to be atomic (i.e. the only one in the system for this particular namespace name).
        /// 
        internal static XNamespace Get(string namespaceName, int index, int count) { 
            Debug.Assert(index >= 0 && index <= namespaceName.Length, "Caller should have checked that index was in bounds");
            Debug.Assert(count >= 0 && index + count <= namespaceName.Length, "Caller should have checked that count was in bounds"); 
 
            if (count == 0) return None;
 
            // Use CompareExchange to ensure that exactly one XHashtable is used to store namespaces
            if (namespaces == null)
                Interlocked.CompareExchange(ref namespaces, new XHashtable(ExtractNamespace, NamespacesCapacity), null);
 
            WeakReference refNamespace;
            XNamespace ns; 
 
            // Keep looping until a non-null namespace has been retrieved
            do { 
                // Attempt to get the WeakReference for the namespace from the hash table
                if (!namespaces.TryGetValue(namespaceName, index, count, out refNamespace)) {
                    // If it is not there, first determine whether it's a special namespace
                    if (count == xmlPrefixNamespace.Length && string.CompareOrdinal(namespaceName, index, xmlPrefixNamespace, 0, count) == 0) return Xml; 
                    if (count == xmlnsPrefixNamespace.Length && string.CompareOrdinal(namespaceName, index, xmlnsPrefixNamespace, 0, count) == 0) return Xmlns;
 
                    // Go ahead and create the namespace and add it to the table 
                    refNamespace = namespaces.Add(new WeakReference(new XNamespace(namespaceName.Substring(index, count))));
                } 

                ns = (refNamespace != null) ? (XNamespace) refNamespace.Target : null;
            }
            while (ns == null); 

            return ns; 
        } 

        ///  
        /// This function is used by the ]]> to extract the local name part from an XName.  The hash table
        /// uses the local name as the hash key.
        /// 
        private static string ExtractLocalName(XName n) { 
            Debug.Assert(n != null, "Null name should never exist here");
            return n.LocalName; 
        } 

        ///  
        /// This function is used by the ]]> to extract the XNamespace that the WeakReference is
        /// referencing.  In cases where the XNamespace has been cleaned up, this function returns null.
        /// 
        private static string ExtractNamespace(WeakReference r) { 
            XNamespace ns;
 
            if (r == null || (ns = (XNamespace) r.Target) == null) 
                return null;
 
            return ns.NamespaceName;
        }

        ///  
        /// Ensure that an XNamespace object for 'namespaceName' has been atomically created.  In other words, all outstanding
        /// references to this particular namespace, on any thread, must all be to the same object.  Care must be taken, 
        /// since other threads can be concurrently calling this method, and the target of a WeakReference can be cleaned up 
        /// at any time by the GC.
        ///  
        private static XNamespace EnsureNamespace(ref WeakReference refNmsp, string namespaceName) {
            WeakReference refOld;

            // Keep looping until a non-null namespace has been retrieved 
            while (true) {
                // Save refNmsp in local variable, so we can work on a value that will not be changed by another thread 
                refOld = refNmsp; 

                if (refOld != null) { 
                    // If the target of the WeakReference is non-null, then we're done--just return the value
                    XNamespace ns = (XNamespace) refOld.Target;
                    if (ns != null) return ns;
                } 

                // Either refNmsp is null, or its target is null, so update it 
                // Make sure to do this atomically, so that we can guarantee atomicity of XNamespace objects 
                Interlocked.CompareExchange(ref refNmsp, new WeakReference(new XNamespace(namespaceName)), refOld);
            } 
        }
    }

    ///  
    /// This is a thread-safe hash table which maps string keys to values of type TValue.  It is assumed that the string key is embedded in the hashed value
    /// and can be extracted via a call to ExtractKeyDelegate (in order to save space and allow cleanup of key if value is released due to a WeakReference 
    /// TValue releasing its target). 
    /// 
    ///  
    /// All methods on this class are thread-safe.
    ///
    /// When the hash table fills up, it is necessary to resize it and rehash all contents.  Because this can be expensive,
    /// a lock is taken, and one thread is responsible for the resize.  Other threads which need to add values must wait 
    /// for the resize to be complete.
    /// 
    /// Thread-Safety Notes 
    /// ===================
    /// 
    /// 1. Because performance and scalability are such a concern with the global name table, I have avoided the use of
    ///    BIFALOs (Big Fat Locks).  Instead, I use CompareExchange, Interlocked.Increment, memory barriers, atomic state objects,
    ///    etc. to avoid locks.  Any changes to code which accesses these variables should be carefully reviewed and tested,
    ///    as it can be *very* tricky.  In particular, if you don't understand the CLR memory model or if you don't know 
    ///    what a memory barrier is, DON'T attempt to modify this code.  A good discussion of these topics can be found at
    ///    . 
    /// 
    /// 2. Because I am not sure if the CLR spec has changed since versions 1.0/1.1, I am assuming the weak memory model that
    ///    is described in the ECMA spec, in which normal writes can be reordered.  This means I must introduce more memory 
    ///    barriers than otherwise would be necessary.
    ///
    /// 3. There are several thread-safety concepts and patterns I utilize in this code:
    ///      a. Publishing -- There are a small number of places where state is exposed, or published, to multiple threads. 
    ///                       These places are marked with the comment "PUBLISH", and are key locations to consider when
    ///                       reviewing the code for thread-safety. 
    /// 
    ///      b. Immutable objects -- Immutable objects initialize their fields once in their constructor and then never modify
    ///                              them again.  As long as care is taken to ensure that initial field values are visible to 
    ///                              other threads before publishing the immutable object itself, immutable objects are
    ///                              completely thread-safe.
    ///
    ///      c. Atomic state objects -- Locks typically are taken when several pieces of state must be updated atomically.  In 
    ///                                 other words, there is a window in which state is inconsistent, and that window must
    ///                                 be protected from view by locking.  However, if a new object is created each time state 
    ///                                 changes (or state changes substantially), then during creation the new object is only 
    ///                                 visible to a single thread.  Once construction is complete, an assignment (guaranteed
    ///                                 atomic) can replace the old state object with the new state object, thus publishing a 
    ///                                 consistent view to all threads.
    ///
    ///      d. Retry -- When several threads contend over shared state which only one is allowed to possess, it is possible
    ///                  to avoid locking by repeatedly attempting to acquire the shared state.  The CompareExchange method 
    ///                  is useful for atomically ensuring that only one thread succeeds, and other threads are notified that
    ///                  they must retry. 
    /// 
    /// 4. All variables which can be written by multiple threads are marked "SHARED STATE".
    ///  
    internal sealed class XHashtable
    {
        private XHashtableState state;                          // SHARED STATE: Contains all XHashtable state, so it can be atomically swapped when resizes occur
 
        private const int StartingHash = (5381 << 16) + 5381;   // Starting hash code value for string keys to be hashed
 
        ///  
        /// Prototype of function which is called to extract a string key value from a hashed value.
        /// Returns null if the hashed value is invalid (e.g. value has been released due to a WeakReference TValue being cleaned up). 
        /// 
        public delegate string ExtractKeyDelegate(TValue value);

        ///  
        /// Construct a new XHashtable with the specified starting capacity.
        ///  
        public XHashtable(ExtractKeyDelegate extractKey, int capacity) { 
            state = new XHashtableState(extractKey, capacity);
        } 

        /// 
        /// Get an existing value from the hash table.  Return false if no such value exists.
        ///  
        public bool TryGetValue(string key, int index, int count, out TValue value) {
            return state.TryGetValue(key, index, count, out value); 
        } 

        ///  
        /// Add a value to the hash table, hashed based on a string key embedded in it.  Return the added value (may be a different object than "value").
        /// 
        public TValue Add(TValue value) {
            TValue newValue; 

            // Loop until value is in hash table 
            while (true) { 
                // Add new value
                // XHashtableState.TryAdd returns false if hash table is not big enough 
                if (state.TryAdd(value, out newValue))
                    return newValue;

                // PUBLISH (state) 
                // Hash table was not big enough, so resize it.
                // We only want one thread to perform a resize, as it is an expensive operation 
                // First thread will perform resize; waiting threads will call Resize(), but should immediately 
                // return since there will almost always be space in the hash table resized by the first thread.
                lock (this) { 
                    XHashtableState newState = state.Resize();

                    // Use memory barrier to ensure that the resized XHashtableState object is fully constructed before it is assigned
                    Thread.MemoryBarrier(); 
                    state = newState;
                } 
            } 
        }
 
        /// 
        /// This class contains all the hash table state.  Rather than creating a bucket object, buckets are structs
        /// packed into an array.  Buckets with the same truncated hash code are linked into lists, so that collisions
        /// can be disambiguated. 
        /// 
        ///  
        /// Note that the "buckets" and "entries" arrays are never themselves written by multiple threads.  Instead, the 
        /// *contents* of the array are written by multiple threads.  Resizing the hash table does not modify these variables,
        /// or even modify the contents of these variables.  Instead, resizing makes an entirely new XHashtableState object 
        /// in which all entries are rehashed.  This strategy allows reader threads to continue finding values in the "old"
        /// XHashtableState, while writer threads (those that need to add a new value to the table) are blocked waiting for
        /// the resize to complete.
        ///  
        private sealed class XHashtableState {
            private int[] buckets;                  // Buckets contain indexes into entries array (bucket values are SHARED STATE) 
            private Entry[] entries;                // Entries contain linked lists of buckets (next pointers are SHARED STATE) 
            private int numEntries;                 // SHARED STATE: Current number of entries (including orphaned entries)
            private ExtractKeyDelegate extractKey;  // Delegate called in order to extract string key embedded in hashed TValue 

            private const int EndOfList = 0;        // End of linked list marker
            private const int FullList = -1;        // Indicates entries should not be added to end of linked list
 
            /// 
            /// Construct a new XHashtableState object with the specified capacity. 
            ///  
            public XHashtableState(ExtractKeyDelegate extractKey, int capacity) {
                Debug.Assert((capacity & (capacity - 1)) == 0, "capacity must be a power of 2"); 
                Debug.Assert(extractKey != null, "extractKey may not be null");

                // Initialize hash table data structures, with specified maximum capacity
                buckets = new int[capacity]; 
                entries = new Entry[capacity];
 
                // Save delegate 
                this.extractKey = extractKey;
            } 

            /// 
            /// If this table is not full, then just return "this".  Otherwise, create and return a new table with
            /// additional capacity, and rehash all values in the table. 
            /// 
            public XHashtableState Resize() { 
                // No need to resize if there are open entries 
                if (numEntries < buckets.Length)
                    return this; 

                int newSize = 0;

                // Determine capacity of resized hash table by first counting number of valid, non-orphaned entries 
                // As this count proceeds, close all linked lists so that no additional entries can be added to them
                for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { 
                    int entryIdx = buckets[bucketIdx]; 

                    if (entryIdx == EndOfList) { 
                        // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize
                        entryIdx = Interlocked.CompareExchange(ref buckets[bucketIdx], FullList, EndOfList);
                    }
 
                    // Loop until we've guaranteed that the list has been counted and closed to further adds
                    while (entryIdx > EndOfList) { 
                        // Count each valid entry 
                        if (extractKey(entries[entryIdx].Value) != null)
                            newSize++; 

                        if (entries[entryIdx].Next == EndOfList) {
                            // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize
                            entryIdx = Interlocked.CompareExchange(ref entries[entryIdx].Next, FullList, EndOfList); 
                        }
                        else { 
                            // Move to next entry in the list 
                            entryIdx = entries[entryIdx].Next;
                        } 
                    }
                    Debug.Assert(entryIdx == EndOfList, "Resize() should only be called by one thread");
                }
 
                // Double number of valid entries; if result is less than current capacity, then use current capacity
                if (newSize < buckets.Length / 2) { 
                    newSize = buckets.Length; 
                }
                else { 
                    newSize = buckets.Length * 2;

                    if (newSize < 0)
                        throw new OverflowException(); 
                }
 
                // Create new hash table with additional capacity 
                XHashtableState newHashtable = new XHashtableState(extractKey, newSize);
 
                // Rehash names (TryAdd will always succeed, since we won't fill the new table)
                // Do not simply walk over entries and add them to table, as that would add orphaned
                // entries.  Instead, walk the linked lists and add each name.
                for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { 
                    int entryIdx = buckets[bucketIdx];
                    TValue newValue; 
 
                    while (entryIdx > EndOfList) {
                        newHashtable.TryAdd(entries[entryIdx].Value, out newValue); 
                        Debug.Assert((object)entries[entryIdx].Value == (object)newValue);

                        entryIdx = entries[entryIdx].Next;
                    } 
                    Debug.Assert(entryIdx == FullList, "Linked list should have been closed when it was counted");
                } 
 
                return newHashtable;
            } 

            /// 
            /// Attempt to find "key" in the table.  If the key exists, return the associated value in "value" and
            /// return true.  Otherwise return false. 
            /// 
            public bool TryGetValue(string key, int index, int count, out TValue value) { 
                int hashCode = ComputeHashCode(key, index, count); 
                int entryIndex = 0;
 
                // If a matching entry is found, return its value
                if (FindEntry(hashCode, key, index, count, ref entryIndex)) {
                    value = entries[entryIndex].Value;
                    return true; 
                }
 
                // No matching entry found, so return false 
                value = default(TValue);
                return false; 
            }

            /// 
            /// Attempt to add "value" to the table, hashed by an embedded string key.  If a value having the same key already exists, 
            /// then return the existing value in "newValue".  Otherwise, return the newly added value in "newValue".
            /// 
            /// If the hash table is full, return false.  Otherwise, return true. 
            /// 
            public bool TryAdd(TValue value, out TValue newValue) { 
                int newEntry, entryIndex;
                string key;
                int hashCode;
 
                // Assume "value" will be added and returned as "newValue"
                newValue = value; 
 
                // Extract the key from the value.  If it's null, then value is invalid and does not need to be added to table.
                key = extractKey(value); 
                if (key == null)
                    return true;

                // Compute hash code over entire length of key 
                hashCode = ComputeHashCode(key, 0, key.Length);
 
                // Assume value is not yet in the hash table, and prepare to add it (if table is full, return false). 
                // Use the entry index returned from Increment, which will never be zero, as zero conflicts with EndOfList.
                // Although this means that the first entry will never be used, it avoids the need to initialize all 
                // starting buckets to the EndOfList value.
                newEntry = Interlocked.Increment(ref numEntries);
                if (newEntry < 0 || newEntry >= buckets.Length)
                    return false; 

                entries[newEntry].Value = value; 
                entries[newEntry].HashCode = hashCode; 

                // Ensure that all writes to the entry can't be reordered past this barrier (or other threads might see new entry 
                // in list before entry has been initialized!).
                Thread.MemoryBarrier();

                // Loop until a matching entry is found, a new entry is added, or linked list is found to be full 
                entryIndex = 0;
                while (!FindEntry(hashCode, key, 0, key.Length, ref entryIndex)) { 
                    // PUBLISH (buckets slot) 
                    // No matching entry found, so add the new entry to the end of the list ("entryIndex" is index of last entry)
                    if (entryIndex == 0) 
                        entryIndex = Interlocked.CompareExchange(ref buckets[hashCode & (buckets.Length - 1)], newEntry, EndOfList);
                    else
                        entryIndex = Interlocked.CompareExchange(ref entries[entryIndex].Next, newEntry, EndOfList);
 
                    // Return true only if the CompareExchange succeeded (happens when replaced value is EndOfList).
                    // Return false if the linked list turned out to be full because another thread is currently resizing 
                    // the hash table.  In this case, entries[newEntry] is orphaned (not part of any linked list) and the 
                    // Add needs to be performed on the new hash table.  Otherwise, keep looping, looking for new end of list.
                    if (entryIndex <= EndOfList) 
                        return entryIndex == EndOfList;
                }

                // Another thread already added the value while this thread was trying to add, so return that instance instead. 
                // Note that entries[newEntry] will be orphaned (not part of any linked list) in this case
                newValue = entries[entryIndex].Value; 
 
                return true;
            } 

            /// 
            /// Searches a linked list of entries, beginning at "entryIndex".  If "entryIndex" is 0, then search starts at a hash bucket instead.
            /// Each entry in the list is matched against the (hashCode, key, index, count) key.  If a matching entry is found, then its 
            /// entry index is returned in "entryIndex" and true is returned.  If no matching entry is found, then the index of the last entry
            /// in the list (or 0 if list is empty) is returned in "entryIndex" and false is returned. 
            ///  
            /// 
            /// This method has the side effect of removing invalid entries from the list as it is traversed. 
            /// 
            private bool FindEntry(int hashCode, string key, int index, int count, ref int entryIndex) {
                int previousIndex = entryIndex;
                int currentIndex; 

                // Set initial value of currentIndex to index of the next entry following entryIndex 
                if (previousIndex == 0) 
                    currentIndex = buckets[hashCode & (buckets.Length - 1)];
                else 
                    currentIndex = previousIndex;

                // Loop while not at end of list
                while (currentIndex > EndOfList) { 

                    // Check for matching hash code, then matching key 
                    if (entries[currentIndex].HashCode == hashCode) { 
                        string keyCompare = extractKey(entries[currentIndex].Value);
 
                        // If the key is invalid, then attempt to remove the current entry from the linked list.
                        // This is thread-safe in the case where the Next field points to another entry, since once a Next field points
                        // to another entry, it will never be modified to be EndOfList or FullList.
                        if (keyCompare == null) { 
                            if (entries[currentIndex].Next > EndOfList) {
                                // PUBLISH (buckets slot or entries slot) 
                                // Entry is invalid, so modify previous entry to point to its next entry 
                                entries[currentIndex].Value = default(TValue);
                                currentIndex = entries[currentIndex].Next; 

                                if (previousIndex == 0)
                                    buckets[hashCode & (buckets.Length - 1)] = currentIndex;
                                else 
                                    entries[previousIndex].Next = currentIndex;
 
                                continue; 
                            }
                        } 
                        else {
                            // Valid key, so compare keys
                            if (count == keyCompare.Length && string.CompareOrdinal(key, index, keyCompare, 0, count) == 0) {
                                // Found match, so return true and matching entry in list 
                                entryIndex = currentIndex;
                                return true; 
                            } 
                        }
                    } 

                    // Move to next entry
                    previousIndex = currentIndex;
                    currentIndex = entries[currentIndex].Next; 
                }
 
                // Return false and last entry in list 
                entryIndex = previousIndex;
                return false; 
            }

            /// 
            /// Compute hash code for a string key (index, count substring of "key").  The algorithm used is the same on used in NameTable.cs in System.Xml. 
            /// 
            private static int ComputeHashCode(string key, int index, int count) { 
                int hashCode = StartingHash; 
                int end = index + count;
                Debug.Assert(key != null, "key should have been checked previously for null"); 

                // Hash the key
                for (int i = index; i < end; i++)
                    hashCode += (hashCode << 7) ^ key[i]; 

                // Mix up hash code a bit more and clear the sign bit.  This code was taken from NameTable.cs in System.Xml. 
                hashCode -= hashCode >> 17; 
                hashCode -= hashCode >> 11;
                hashCode -= hashCode >> 5; 
                return hashCode & 0x7FFFFFFF;
            }

            ///  
            /// Hash table entry.  The "Value" and "HashCode" fields are filled during initialization, and are never changed.  The "Next"
            /// field is updated when a new entry is chained to this one, and therefore care must be taken to ensure that updates to 
            /// this field are thread-safe. 
            /// 
            private struct Entry 
            {
                public TValue Value;    // Hashed value
                public int HashCode;    // Hash code of string key (equal to extractKey(Value).GetHashCode())
                public int Next;        // SHARED STATE: Points to next entry in linked list 
            }
        } 
    } 

    ///  
    /// Represents a node or an attribute in an XML tree.
    /// 
    public abstract class XObject : IXmlLineInfo
    { 
        internal XContainer parent;
        internal object annotations; 
 
        internal XObject() { }
 
        /// 
        /// Get the BaseUri for this .
        /// 
        [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Back-compat with System.Xml.")] 
        public string BaseUri {
            get { 
                XObject o = this; 
                while (true) {
                    while (o != null && o.annotations == null) { 
                        o = o.parent;
                    }
                    if (o == null) break;
                    BaseUriAnnotation a = o.Annotation(); 
                    if (a != null) return a.baseUri;
                    o = o.parent; 
                } 
                return string.Empty;
            } 
        }

        /// 
        /// Gets the XDocument object for this . 
        /// 
        public XDocument Document { 
            get { 
                XObject n = this;
                while (n.parent != null) n = n.parent; 
                return n as XDocument;
            }
        }
 
        /// 
        /// Gets the node type for this . 
        ///  
        public abstract XmlNodeType NodeType { get; }
 
        /// 
        /// Gets the parent  of this .
        /// 
        ///  
        /// If this  has no parent , this property returns null.
        ///  
        public XElement Parent { 
            get { return parent as XElement; }
        } 

        /// 
        /// Adds an object to the annotation list of this .
        ///  
        /// The annotation to add.
        public void AddAnnotation(object annotation) { 
            if (annotation == null) throw new ArgumentNullException("annotation"); 
            if (annotations == null) {
                annotations = annotation is object[] ? new object[] { annotation } : annotation; 
            }
            else {
                object[] a = annotations as object[];
                if (a == null) { 
                    annotations = new object[] { annotations, annotation };
                } 
                else { 
                    int i = 0;
                    while (i < a.Length && a[i] != null) i++; 
                    if (i == a.Length) {
                        Array.Resize(ref a, i * 2);
                        annotations = a;
                    } 
                    a[i] = annotation;
                } 
            } 
        }
 
        /// 
        /// Returns the first annotation object of the specified type from the list of annotations
        /// of this .
        ///  
        /// The type of the annotation to retrieve.
        ///  
        /// The first matching annotation object, or null 
        /// if no annotation is the specified type.
        ///  
        public object Annotation(Type type) {
            if (type == null) throw new ArgumentNullException("type");
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) return annotations; 
                } 
                else {
                    for (int i = 0; i < a.Length; i++) { 
                        object obj = a[i];
                        if (obj == null) break;
                        if (type.IsInstanceOfType(obj)) return obj;
                    } 
                }
            } 
            return null; 
        }
 
        /// 
        /// Returns the first annotation object of the specified type from the list of annotations
        /// of this .
        ///  
        /// The type of the annotation to retrieve.
        ///  
        /// The first matching annotation object, or null if no annotation 
        /// is the specified type.
        ///  
        public T Annotation() where T : class
        {
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) return annotations as T;
                for (int i = 0; i < a.Length; i++) { 
                    object obj = a[i]; 
                    if (obj == null) break;
                    T result = obj as T; 
                    if (result != null) return result;
                }
            }
            return null; 
        }
 
        ///  
        /// Returns an enumerable collection of annotations of the specified type
        /// for this . 
        /// 
        /// The type of the annotations to retrieve.
        /// An enumerable collection of annotations for this XObject.
        public IEnumerable Annotations(Type type) { 
            if (type == null) throw new ArgumentNullException("type");
            return AnnotationsIterator(type); 
        } 

        IEnumerable AnnotationsIterator(Type type) { 
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) yield return annotations; 
                }
                else { 
                    for (int i = 0; i < a.Length; i++) { 
                        object obj = a[i];
                        if (obj == null) break; 
                        if (type.IsInstanceOfType(obj)) yield return obj;
                    }
                }
            } 
        }
 
        ///  
        /// Returns an enumerable collection of annotations of the specified type
        /// for this . 
        /// 
        /// The type of the annotations to retrieve.
        /// An enumerable collection of annotations for this XObject.
        public IEnumerable Annotations() where T : class { 
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) { 
                    T result = annotations as T;
                    if (result != null) yield return result; 
                }
                else {
                    for (int i = 0; i < a.Length; i++) {
                        object obj = a[i]; 
                        if (obj == null) break;
                        T result = obj as T; 
                        if (result != null) yield return result; 
                    }
                } 
            }
        }

        ///  
        /// Removes the annotations of the specified type from this .
        ///  
        /// The type of annotations to remove. 
        public void RemoveAnnotations(Type type) {
            if (type == null) throw new ArgumentNullException("type"); 
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) annotations = null; 
                }
                else { 
                    int i = 0, j = 0; 
                    while (i < a.Length) {
                        object obj = a[i]; 
                        if (obj == null) break;
                        if (!type.IsInstanceOfType(obj)) a[j++] = obj;
                        i++;
                    } 
                    if (j == 0) {
                        annotations = null; 
                    } 
                    else {
                        while (j < i) a[j++] = null; 
                    }
                }
            }
        } 

        ///  
        /// Removes the annotations of the specified type from this . 
        /// 
        /// The type of annotations to remove. 
        public void RemoveAnnotations() where T : class {
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) { 
                    if (annotations is T) annotations = null;
                } 
                else { 
                    int i = 0, j = 0;
                    while (i < a.Length) { 
                        object obj = a[i];
                        if (obj == null) break;
                        if (!(obj is T)) a[j++] = obj;
                        i++; 
                    }
                    if (j == 0) { 
                        annotations = null; 
                    }
                    else { 
                        while (j < i) a[j++] = null;
                    }
                }
            } 
        }
 
        ///  
        /// Occurs when this  or any of its descendants have changed.
        ///  
        public event EventHandler Changed {
            add {
                if (value == null) return;
                XObjectChangeAnnotation a = Annotation(); 
                if (a == null) {
                    a = new XObjectChangeAnnotation(); 
                    AddAnnotation(a); 
                }
                a.changed += value; 
            }
            remove {
                if (value == null) return;
                XObjectChangeAnnotation a = Annotation(); 
                if (a == null) return;
                a.changed -= value; 
                if (a.changing == null && a.changed == null) { 
                    RemoveAnnotations();
                } 
            }
        }

        ///  
        /// Occurs when this  or any of its descendants are about to change.
        ///  
        public event EventHandler Changing { 
            add {
                if (value == null) return; 
                XObjectChangeAnnotation a = Annotation();
                if (a == null) {
                    a = new XObjectChangeAnnotation();
                    AddAnnotation(a); 
                }
                a.changing += value; 
            } 
            remove {
                if (value == null) return; 
                XObjectChangeAnnotation a = Annotation();
                if (a == null) return;
                a.changing -= value;
                if (a.changing == null && a.changed == null) { 
                    RemoveAnnotations();
                } 
            } 
        }
 
        bool IXmlLineInfo.HasLineInfo() {
            return Annotation() != null;
        }
 
        int IXmlLineInfo.LineNumber {
            get { 
                LineInfoAnnotation a = Annotation(); 
                if (a != null) return a.lineNumber;
                return 0; 
            }
        }

        int IXmlLineInfo.LinePosition { 
            get {
                LineInfoAnnotation a = Annotation(); 
                if (a != null) return a.linePosition; 
                return 0;
            } 
        }

        internal bool HasBaseUri {
            get { 
                return Annotation() != null;
            } 
        } 

        internal bool NotifyChanged(object sender, XObjectChangeEventArgs e) { 
            bool notify = false;
            XObject o = this;
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent;
                } 
                if (o == null) break; 
                XObjectChangeAnnotation a = o.Annotation();
                if (a != null) { 
                    notify = true;
                    if (a.changed != null) {
                        a.changed(sender, e);
                    } 
                }
                o = o.parent; 
            } 
            return notify;
        } 

        internal bool NotifyChanging(object sender, XObjectChangeEventArgs e) {
            bool notify = false;
            XObject o = this; 
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent; 
                }
                if (o == null) break; 
                XObjectChangeAnnotation a = o.Annotation();
                if (a != null) {
                    notify = true;
                    if (a.changing != null) { 
                        a.changing(sender, e);
                    } 
                } 
                o = o.parent;
            } 
            return notify;
        }

        internal void SetBaseUri(string baseUri) { 
            AddAnnotation(new BaseUriAnnotation(baseUri));
        } 
 
        internal void SetLineInfo(int lineNumber, int linePosition) {
            AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition)); 
        }

        internal bool SkipNotify() {
            XObject o = this; 
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent; 
                }
                if (o == null) return true; 
                if (o.Annotations() != null) return false;
                o = o.parent;
            }
        } 
    }
 
    class BaseUriAnnotation 
    {
        internal string baseUri; 

        public BaseUriAnnotation(string baseUri) {
            this.baseUri = baseUri;
        } 
    }
 
    class LineInfoAnnotation 
    {
        internal int lineNumber; 
        internal int linePosition;

        public LineInfoAnnotation(int lineNumber, int linePosition) {
            this.lineNumber = lineNumber; 
            this.linePosition = linePosition;
        } 
    } 

    class XObjectChangeAnnotation 
    {
        internal EventHandler changing;
        internal EventHandler changed;
 
        public XObjectChangeAnnotation() {
        } 
    } 

    ///  
    /// Specifies the event type when an event is raised for an .
    /// 
    public enum XObjectChange
    { 
        /// 
        /// An  has been or will be added to an . 
        ///  
        Add,
 
        /// 
        /// An  has been or will be removed from an .
        /// 
        Remove, 

        ///  
        /// An  has been or will be renamed. 
        /// 
        Name, 

        /// 
        /// The value of an  has been or will be changed.
        /// There is a special case for elements. Change in the serialization 
        /// of an empty element (either from an empty tag to start/end tag
        /// pair or vice versa) raises this event. 
        ///  
        Value,
    } 

    /// 
    /// Provides data for the  and  events.
    ///  
    public class XObjectChangeEventArgs : EventArgs
    { 
        XObjectChange objectChange; 

        ///  
        /// Event argument for a  change event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")]
        public static readonly XObjectChangeEventArgs Add = new XObjectChangeEventArgs(XObjectChange.Add); 

        ///  
        /// Event argument for a  change event. 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")] 
        public static readonly XObjectChangeEventArgs Remove = new XObjectChangeEventArgs(XObjectChange.Remove);

        /// 
        /// Event argument for a  change event. 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")] 
        public static readonly XObjectChangeEventArgs Name = new XObjectChangeEventArgs(XObjectChange.Name); 

        ///  
        /// Event argument for a  change event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")]
        public static readonly XObjectChangeEventArgs Value = new XObjectChangeEventArgs(XObjectChange.Value); 

        ///  
        /// Initializes a new instance of the  class. 
        /// 
        public XObjectChangeEventArgs(XObjectChange objectChange) { 
            this.objectChange = objectChange;
        }

        ///  
        /// Gets the type () of change.
        ///  
        public XObjectChange ObjectChange { 
            get { return objectChange; }
        } 
    }

    /// 
    /// Represents nodes (elements, comments, document type, processing instruction, 
    /// and text nodes) in the XML tree.
    ///  
    ///  
    /// Nodes in the XML tree consist of objects of the following classes:
    /// , 
    /// ,
    /// ,
    /// ,
    /// , 
    /// 
    /// Note that an  is not an . 
    ///  
    public abstract class XNode : XObject
    { 
        static XNodeDocumentOrderComparer documentOrderComparer;
        static XNodeEqualityComparer equalityComparer;

        internal XNode next; 

        internal XNode() { } 
 
        /// 
        /// Gets the next sibling node of this node. 
        /// 
        /// 
        /// If this property does not have a parent, or if there is no next node,
        /// then this property returns null. 
        /// 
        public XNode NextNode { 
            get { 
                return parent == null || this == parent.content ? null : next;
            } 
        }

        /// 
        /// Gets the previous sibling node of this node. 
        /// 
        ///  
        /// If this property does not have a parent, or if there is no previous node, 
        /// then this property returns null.
        ///  
        public XNode PreviousNode {
            get {
                if (parent == null) return null;
                XNode n = ((XNode)parent.content).next; 
                XNode p = null;
                while (n != this) { 
                    p = n; 
                    n = n.next;
                } 
                return p;
            }
        }
 
        /// 
        /// Gets a comparer that can compare the relative position of two nodes. 
        ///  
        public static XNodeDocumentOrderComparer DocumentOrderComparer {
            get { 
                if (documentOrderComparer == null) documentOrderComparer = new XNodeDocumentOrderComparer();
                return documentOrderComparer;
            }
        } 

        ///  
        /// Gets a comparer that can compare two nodes for value equality. 
        /// 
        public static XNodeEqualityComparer EqualityComparer { 
            get {
                if (equalityComparer == null) equalityComparer = new XNodeEqualityComparer();
                return equalityComparer;
            } 
        }
 
        ///  
        /// Adds the specified content immediately after this node. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects,
        /// or null.
        /// 
        ///  
        /// Adds the specified content immediately after this node.
        ///  
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added after this node. 
        /// 
        /// 
        /// Thrown if the parent is null.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void AddAfterSelf(object content) { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            new Inserter(parent, this).Add(content);
        }
 
        /// 
        /// Adds the specified content immediately after this node. 
        ///  
        /// 
        /// A parameter list of content objects. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        ///  
        /// Thrown if the parent is null. 
        /// 
        public void AddAfterSelf(params object[] content) { 
            AddAfterSelf((object)content);
        }

        ///  
        /// Adds the specified content immediately before this node. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, 
        /// or null.
        ///  
        /// 
        /// Adds the specified content immediately before this node.
        /// 
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added after this node. 
        ///  
        /// 
        /// Thrown if the parent is null. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void AddBeforeSelf(object content) { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent)); 
            XNode p = (XNode)parent.content;
            while (p.next != this) p = p.next; 
            if (p == parent.content) p = null;
            new Inserter(parent, p).Add(content);
        }
 
        /// 
        /// Adds the specified content immediately before this node. 
        ///  
        /// 
        /// A parameter list of content objects. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        ///  
        /// Thrown if the parent is null. 
        /// 
        public void AddBeforeSelf(params object[] content) { 
            AddBeforeSelf((object)content);
        }

        ///  
        /// Returns an collection of the ancestor elements for this node.
        /// Optionally an node name can be specified to filter for a specific ancestor element. 
        ///  
        /// 
        /// Returns a collection of the ancestor elements of this node. 
        /// 
        /// 
        /// The ancestor elements of this node.
        ///  
        /// 
        /// This method will not return itself in the results. 
        ///  
        public IEnumerable Ancestors() {
            return GetAncestors(null, false); 
        }

        /// 
        /// Returns a collection of the ancestor elements of this node with the specified name. 
        /// 
        ///  
        /// The name of the ancestor elements to find. 
        /// 
        ///  
        /// A collection of the ancestor elements of this node with the specified name.
        /// 
        /// 
        /// This method will not return itself in the results. 
        /// 
        public IEnumerable Ancestors(XName name) { 
            return name != null ? GetAncestors(name, false) : XElement.EmptySequence; 
        }
 
        /// 
        /// Compares two nodes to determine their relative XML document order.
        /// 
        /// First node to compare. 
        /// Second node to compare.
        ///  
        /// 0 if the nodes are equal; -1 if n1 is before n2; 1 if n1 is after n2. 
        /// 
        ///  
        /// Thrown if the two nodes do not share a common ancestor.
        /// 
        [SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Reviewed.")]
        public static int CompareDocumentOrder(XNode n1, XNode n2) { 
            if (n1 == n2) return 0;
            if (n1 == null) return -1; 
            if (n2 == null) return 1; 
            if (n1.parent != n2.parent) {
                int height = 0; 
                XNode p1 = n1;
                while (p1.parent != null) {
                    p1 = p1.parent;
                    height++; 
                }
                XNode p2 = n2; 
                while (p2.parent != null) { 
                    p2 = p2.parent;
                    height--; 
                }
                if (p1 != p2) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingAncestor));
                if (height < 0) {
                    do { 
                        n2 = n2.parent;
                        height++; 
                    } while (height != 0); 
                    if (n1 == n2) return -1;
                } 
                else if (height > 0) {
                    do {
                        n1 = n1.parent;
                        height--; 
                    } while (height != 0);
                    if (n1 == n2) return 1; 
                } 
                while (n1.parent != n2.parent) {
                    n1 = n1.parent; 
                    n2 = n2.parent;
                }
            }
            else if (n1.parent == null) { 
                throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingAncestor));
            } 
            XNode n = (XNode)n1.parent.content; 
            while (true) {
                n = n.next; 
                if (n == n1) return -1;
                if (n == n2) return 1;
            }
        } 

        ///  
        /// Creates an  for the node. 
        /// 
        /// An  that can be used to read the node and its descendants. 
        public XmlReader CreateReader() {
            return new XNodeReader(this, null);
        }
 
        /// 
        /// Returns a collection of the sibling nodes after this node, in document order. 
        ///  
        /// 
        /// This method only includes sibling nodes in the returned collection. 
        /// 
        /// The nodes after this node.
        public IEnumerable NodesAfterSelf() {
            XNode n = this; 
            while (n.parent != null && n != n.parent.content) {
                n = n.next; 
                yield return n; 
            }
        } 

        /// 
        /// Returns a collection of the sibling nodes before this node, in document order.
        ///  
        /// 
        /// This method only includes sibling nodes in the returned collection. 
        ///  
        /// The nodes after this node.
        public IEnumerable NodesBeforeSelf() { 
            if (parent != null) {
                XNode n = (XNode)parent.content;
                do {
                    n = n.next; 
                    if (n == this) break;
                    yield return n; 
                } while (parent != null && parent == n.parent); 
            }
        } 

        /// 
        /// Returns a collection of the sibling element nodes after this node, in document order.
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        ///  
        /// The element nodes after this node.
        public IEnumerable ElementsAfterSelf() { 
            return GetElementsAfterSelf(null);
        }

        ///  
        /// Returns a collection of the sibling element nodes with the specified name
        /// after this node, in document order. 
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        /// 
        /// The element nodes after this node with the specified name.
        /// The name of elements to enumerate.
        public IEnumerable ElementsAfterSelf(XName name) { 
            return name != null ? GetElementsAfterSelf(name) : XElement.EmptySequence;
        } 
 
        /// 
        /// Returns a collection of the sibling element nodes before this node, in document order. 
        /// 
        /// 
        /// This method only includes sibling element nodes in the returned collection.
        ///  
        /// The element nodes before this node.
        public IEnumerable ElementsBeforeSelf() { 
            return GetElementsBeforeSelf(null); 
        }
 
        /// 
        /// Returns a collection of the sibling element nodes with the specified name
        /// before this node, in document order.
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        ///  
        /// The element nodes before this node with the specified name.
        /// The name of elements to enumerate. 
        public IEnumerable ElementsBeforeSelf(XName name) {
            return name != null ? GetElementsBeforeSelf(name) : XElement.EmptySequence;
        }
 
        /// 
        /// Determines if the current node appears after a specified node 
        /// in terms of document order. 
        /// 
        /// The node to compare for document order. 
        /// True if this node appears after the specified node; false if not.
        public bool IsAfter(XNode node) {
            return CompareDocumentOrder(this, node) > 0;
        } 

        ///  
        /// Determines if the current node appears before a specified node 
        /// in terms of document order.
        ///  
        /// The node to compare for document order.
        /// True if this node appears before the specified node; false if not.
        public bool IsBefore(XNode node) {
            return CompareDocumentOrder(this, node) < 0; 
        }
 
        ///  
        /// Creates an  from an .
        /// The runtime type of the node is determined by the node type 
        /// () of the first node encountered
        /// in the reader.
        /// 
        /// An  positioned at the node to read into this . 
        /// An  that contains the nodes read from the reader.
        ///  
        /// Thrown if the  is not positioned on a recognized node type. 
        /// 
        public static XNode ReadFrom(XmlReader reader) { 
            if (reader == null) throw new ArgumentNullException("reader");
            if (reader.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive));
            switch (reader.NodeType) {
                case XmlNodeType.Text: 
                case XmlNodeType.SignificantWhitespace:
                case XmlNodeType.Whitespace: 
                    return new XText(reader); 
                case XmlNodeType.CDATA:
                    return new XCData(reader); 
                case XmlNodeType.Comment:
                    return new XComment(reader);
                case XmlNodeType.DocumentType:
                    return new XDocumentType(reader); 
                case XmlNodeType.Element:
                    return new XElement(reader); 
                case XmlNodeType.ProcessingInstruction: 
                    return new XProcessingInstruction(reader);
                default: 
                    throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, reader.NodeType));
            }
        }
 
        /// 
        /// Removes this XNode from the underlying XML tree. 
        ///  
        /// 
        /// Thrown if the parent is null. 
        /// 
        public void Remove() {
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            parent.RemoveNode(this); 
        }
 
        ///  
        /// Replaces this node with the specified content. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects,
        /// or null.
        /// 
        ///  
        /// Replaces the content of this .
        ///  
        /// Content that replaces this node. 
        public void ReplaceWith(object content) {
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent)); 
            XContainer c = parent;
            XNode p = (XNode)parent.content;
            while (p.next != this) p = p.next;
            if (p == parent.content) p = null; 
            parent.RemoveNode(this);
            if (p != null && p.parent != c) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
            new Inserter(c, p).Add(content); 
        }
 
        /// 
        /// Replaces this node with the specified content.
        /// 
        /// Content that replaces this node. 
        public void ReplaceWith(params object[] content) {
            ReplaceWith((object)content); 
        } 

        ///  
        /// Provides the formatted XML text representation.
        /// 
        /// A formatted XML string.
        public override string ToString() { 
            return GetXmlString(SaveOptions.None);
        } 
 
        /// 
        /// Provides the XML text representation. 
        /// 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        /// An XML string.
        public string ToString(SaveOptions options) { 
            return GetXmlString(options); 
        }
 
        /// 
        /// Compares the values of two nodes, including the values of all descendant nodes.
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// true if the nodes are equal, false otherwise. 
        ///  
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two  objects of different types are never equal. Two 
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of equal content nodes. 
        /// Two s are equal if their root nodes are equal. Two
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same 
        /// target and data. Two  nodes are equal if the have the
        /// same name, public id, system id, and internal subset. 
        [SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Reviewed.")]
        public static bool DeepEquals(XNode n1, XNode n2) {
            if (n1 == n2) return true;
            if (n1 == null || n2 == null) return false; 
            return n1.DeepEquals(n2);
        } 
 
        /// 
        /// Write the current node to an . 
        /// 
        /// The  to write the current node into.
        public abstract void WriteTo(XmlWriter writer);
 
        internal virtual void AppendText(StringBuilder sb) {
        } 
 
        internal abstract XNode CloneNode();
 
        internal abstract bool DeepEquals(XNode node);

        internal IEnumerable GetAncestors(XName name, bool self) {
            XElement e = (self ? this : parent) as XElement; 
            while (e != null) {
                if (name == null || e.name == name) yield return e; 
                e = e.parent as XElement; 
            }
        } 

        IEnumerable GetElementsAfterSelf(XName name) {
            XNode n = this;
            while (n.parent != null && n != n.parent.content) { 
                n = n.next;
                XElement e = n as XElement; 
                if (e != null && (name == null || e.name == name)) yield return e; 
            }
        } 

        IEnumerable GetElementsBeforeSelf(XName name) {
            if (parent != null) {
                XNode n = (XNode)parent.content; 
                do {
                    n = n.next; 
                    if (n == this) break; 
                    XElement e = n as XElement;
                    if (e != null && (name == null || e.name == name)) yield return e; 
                } while (parent != null && parent == n.parent);
            }
        }
 
        internal abstract int GetDeepHashCode();
 
        // The settings simulate a non-validating processor with the external 
        // entity resolution disabled. The processing of the internal subset is
        // enabled by default. In order to prevent DoS attacks, the expanded 
        // size of the internal subset is limited to 10 million characters.
        internal static XmlReaderSettings GetXmlReaderSettings(LoadOptions o) {
            XmlReaderSettings rs = new XmlReaderSettings();
            if ((o & LoadOptions.PreserveWhitespace) == 0) rs.IgnoreWhitespace = true; 
            rs.ProhibitDtd = false;
            rs.MaxCharactersFromEntities = (long)1e7; 
            rs.XmlResolver = null; 
            return rs;
        } 

        internal static XmlWriterSettings GetXmlWriterSettings(SaveOptions o) {
            XmlWriterSettings ws = new XmlWriterSettings();
            if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true; 
            return ws;
        } 
 
        string GetXmlString(SaveOptions o) {
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) { 
                XmlWriterSettings ws = new XmlWriterSettings();
                ws.OmitXmlDeclaration = true;
                if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true;
                if (this is XText) ws.ConformanceLevel = ConformanceLevel.Fragment; 
                using (XmlWriter w = XmlWriter.Create(sw, ws)) {
                    XDocument n = this as XDocument; 
                    if (n != null) { 
                        n.WriteContentTo(w);
                    } 
                    else {
                        WriteTo(w);
                    }
                } 
                return sw.ToString();
            } 
        } 
    }
 
    /// 
    /// Contains functionality to compare nodes for their document order.
    /// This class cannot be inherited.
    ///  
    public sealed class XNodeDocumentOrderComparer: IComparer, IComparer
    { 
        ///  
        /// Compares two nodes to determine their relative XML document order.
        ///  
        /// The first node to compare.
        /// The second node to compare.
        /// 
        /// 0 if the nodes are equal; 
        /// -1 if x is before y;
        /// 1 if x is after y. 
        ///  
        /// 
        /// Thrown if the two nodes do not share a common ancestor. 
        /// 
        public int Compare(XNode x, XNode y) {
            return XNode.CompareDocumentOrder(x, y);
        } 

        ///  
        /// Compares two nodes to determine their relative XML document order. 
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// 
        /// 0 if the nodes are equal;
        /// -1 if x is before y; 
        /// 1 if x is after y.
        ///  
        ///  
        /// Thrown if the two nodes do not share a common ancestor.
        ///  
        /// 
        /// Thrown if either of the two nodes are not derived from XNode.
        /// 
        int IComparer.Compare(object x, object y) { 
            XNode n1 = x as XNode;
            if (n1 == null && x != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "x"); 
            XNode n2 = y as XNode; 
            if (n2 == null && y != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "y");
            return Compare(n1, n2); 
        }
    }

    ///  
    /// Contains functionality to compare nodes for value equality.
    /// This class cannot be inherited. 
    ///  
    public sealed class XNodeEqualityComparer: IEqualityComparer, IEqualityComparer
    { 
        /// 
        /// Compares the values of two nodes.
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// true if the nodes are equal, false otherwise. 
        ///  
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two s of different types are never equal. Two 
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of pairwise equal content nodes. 
        /// Two s are equal if their root nodes are equal. Two
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same 
        /// target and data. Two  nodes are equal if the have the
        /// same name, public id, system id, and internal subset. 
        /// 
        public bool Equals(XNode x, XNode y) {
            return XNode.DeepEquals(x, y);
        } 

        ///  
        /// Returns a hash code based on an  objects value. 
        /// 
        /// The node to hash. 
        /// A value-based hash code for the node.
        /// 
        /// The  class's implementation of 
        /// is based on the referential identity of the node. This method computes a 
        /// hash code based on the value of the node.
        ///  
        public int GetHashCode(XNode obj) { 
            return obj != null ? obj.GetDeepHashCode() : 0;
        } 

        /// 
        /// Compares the values of two nodes.
        ///  
        /// The first node to compare.
        /// The second node to compare. 
        /// true if the nodes are equal, false otherwise. 
        /// 
        /// A null node is equal to another null node but unequal to a non-null 
        /// node. Two s of different types are never equal. Two
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing 
        /// instructions, contain two equal length sequences of pairwise equal content nodes.
        /// Two s are equal if their root nodes are equal. Two 
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same
        /// target and data. Two  nodes are equal if the have the 
        /// same name, public id, system id, and internal subset.
        /// 
        bool IEqualityComparer.Equals(object x, object y) {
            XNode n1 = x as XNode; 
            if (n1 == null && x != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "x");
            XNode n2 = y as XNode; 
            if (n2 == null && y != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "y"); 
            return Equals(n1, n2);
        } 

        /// 
        /// Returns a hash code based on a node's value.
        ///  
        /// The node to hash.
        /// A value-based hash code for the node. 
        ///  
        /// The  class's implementation of 
        /// is based on the referential identity of the node. This method computes a 
        /// hash code based on the value of the node.
        /// 
        int IEqualityComparer.GetHashCode(object obj) {
            XNode n = obj as XNode; 
            if (n == null && obj != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "obj");
            return GetHashCode(n); 
        } 
    }
 
    /// 
    /// Represents a text node.
    /// 
    public class XText : XNode 
    {
        internal string text; 
 
        /// 
        /// Initializes a new instance of the XText class. 
        /// 
        /// The string that contains the value of the text node.
        public XText(string value) {
            if (value == null) throw new ArgumentNullException("value"); 
            text = value;
        } 
 
        /// 
        /// Initializes a new instance of the XText class from another XText object. 
        /// 
        /// The text node to copy from.
        public XText(XText other) {
            if (other == null) throw new ArgumentNullException("other"); 
            text = other.text;
        } 
 
        internal XText(XmlReader r) {
            text = r.Value; 
            r.Read();
        }

        ///  
        /// Gets the node type for this node.
        ///  
        ///  
        /// This property will always return XmlNodeType.Text.
        ///  
        public override XmlNodeType NodeType {
            get {
                return XmlNodeType.Text;
            } 
        }
 
        ///  
        /// Gets or sets the value of this node.
        ///  
        public string Value {
            get {
                return text;
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                text = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        }

        ///  
        /// Write this  to the given .
        ///  
        ///  
        /// The  to write this  to.
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            if (parent is XDocument) {
                writer.WriteWhitespace(text); 
            }
            else { 
                writer.WriteString(text); 
            }
        } 

        internal override void AppendText(StringBuilder sb) {
            sb.Append(text);
        } 

        internal override XNode CloneNode() { 
            return new XText(this); 
        }
 
        internal override bool DeepEquals(XNode node) {
            return node != null && NodeType == node.NodeType && text == ((XText)node).text;
        }
 
        internal override int GetDeepHashCode() {
            return text.GetHashCode(); 
        } 
    }
 
    /// 
    /// Represents a text node that contains CDATA.
    /// 
    public class XCData : XText 
    {
        ///  
        /// Initializes a new instance of the XCData class. 
        /// 
        /// The string that contains the value of the XCData node. 
        public XCData(string value) : base(value) { }

        /// 
        /// Initializes a new instance of the XCData class from another XCData object. 
        /// 
        /// Text node to copy from 
        public XCData(XCData other) : base(other) { } 

        internal XCData(XmlReader r) : base(r) { } 

        /// 
        /// Gets the node type for this node.
        ///  
        /// 
        /// This property will always return XmlNodeType.CDATA. 
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.CDATA;
            }
        }
 
        /// 
        /// Write this  to the given . 
        ///  
        /// 
        /// The  to write this  to. 
        /// 
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            writer.WriteCData(text); 
        }
 
        internal override XNode CloneNode() { 
            return new XCData(this);
        } 
    }

    /// 
    /// Represents a node that can contain other nodes. 
    /// 
    ///  
    /// The two classes that derive from  are 
    ///  and .
    ///  
    public abstract class XContainer : XNode
    {
        internal object content;
 
        internal XContainer() { }
 
        internal XContainer(XContainer other) { 
            if (other == null) throw new ArgumentNullException("other");
            if (other.content is string) { 
                this.content = other.content;
            }
            else {
                XNode n = (XNode)other.content; 
                if (n != null) {
                    do { 
                        n = n.next; 
                        AppendNodeSkipNotify(n.CloneNode());
                    } while (n != other.content); 
                }
            }
        }
 
        /// 
        /// Get the first child node of this node. 
        ///  
        public XNode FirstNode {
            get { 
                XNode last = LastNode;
                return last != null ? last.next : null;
            }
        } 

        ///  
        /// Get the last child node of this node. 
        /// 
        public XNode LastNode { 
            get {
                if (content == null) return null;
                XNode n = content as XNode;
                if (n != null) return n; 
                string s = content as string;
                if (s != null) { 
                    if (s.Length == 0) return null; 
                    XText t = new XText(s);
                    t.parent = this; 
                    t.next = t;
                    Interlocked.CompareExchange(ref content, t, s);
                }
                return (XNode)content; 
            }
        } 
 
        /// 
        /// Adds the specified content as a child (or as children) to this XContainer. The 
        /// content can be simple content, a collection of content objects, a parameter list
        /// of content objects, or null.
        /// 
        ///  
        /// Adds the specified content as a child (or children) of this XContainer.
        ///  
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added. 
        /// 
        /// 
        /// When adding simple content, a number of types may be passed to this method.
        /// Valid types include: 
        /// 
        /// string 
        /// double 
        /// float
        /// decimal 
        /// bool
        /// DateTime
        /// DateTimeOffset
        /// TimeSpan 
        /// Any type implementing ToString()
        /// Any type implementing IEnumerable 
        /// 
        /// 
        /// When adding complex content, a number of types may be passed to this method. 
        /// 
        /// XObject
        /// XNode
        /// XAttribute 
        /// Any type implementing IEnumerable
        ///  
        /// 
        /// If an object implements IEnumerable, then the collection in the object is enumerated,
        /// and all items in the collection are added. If the collection contains simple content, 
        /// then the simple content in the collection is concatenated and added as a single
        /// string of simple content. If the collection contains complex content, then each item
        /// in the collection is added separately.
        /// 
        /// If content is null, nothing is added. This allows the results of a query to be passed
        /// as content. If the query returns null, no contents are added, and this method does not 
        /// throw a NullReferenceException. 
        ///
        /// Attributes and simple content can't be added to a document. 
        ///
        /// An added attribute must have a unique name within the element to
        /// which it is being added.
        ///  
        public void Add(object content) {
            if (SkipNotify()) { 
                AddContentSkipNotify(content); 
                return;
            } 
            if (content == null) return;
            XNode n = content as XNode;
            if (n != null) {
                AddNode(n); 
                return;
            } 
            string s = content as string; 
            if (s != null) {
                AddString(s); 
                return;
            }
            XAttribute a = content as XAttribute;
            if (a != null) { 
                AddAttribute(a);
                return; 
            } 
            XStreamingElement x = content as XStreamingElement;
            if (x != null) { 
                AddNode(new XElement(x));
                return;
            }
            object[] o = content as object[]; 
            if (o != null) {
                foreach (object obj in o) Add(obj); 
                return; 
            }
            IEnumerable e = content as IEnumerable; 
            if (e != null) {
                foreach (object obj in e) Add(obj);
                return;
            } 
            AddString(GetStringValue(content));
        } 
 
        /// 
        /// Adds the specified content as a child (or children) of this XContainer. 
        /// 
        /// 
        /// A parameter list of content objects.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void Add(params object[] content) { 
            Add((object)content);
        }

        ///  
        /// Adds the specified content as the first child (or children) of this document or element. The
        /// content can be simple content, a collection of content objects, a parameter 
        /// list of content objects, or null. 
        /// 
        ///  
        /// Adds the specified content as the first child (or children) of this document or element.
        /// 
        /// 
        /// A content object containing simple content or a collection of content objects 
        /// to be added.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void AddFirst(object content) {
            new Inserter(this, null).Add(content);
        } 

        ///  
        /// Adds the specified content as the first children of this document or element. 
        /// 
        ///  
        /// A parameter list of content objects.
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        ///  
        /// Thrown if the parent is null.
        ///  
        public void AddFirst(params object[] content) {
            AddFirst((object)content);
        }
 
        /// 
        /// Creates an  used to add either nodes 
        /// or attributes to the . The later option 
        /// applies only for .
        ///  
        /// An 
        public XmlWriter CreateWriter() {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.ConformanceLevel = this is XDocument ? ConformanceLevel.Document : ConformanceLevel.Fragment; 
            return XmlWriter.Create(new XNodeBuilder(this), settings);
        } 
 
        /// 
        /// Get descendant elements plus leaf nodes contained in an  
        /// 
        /// IEnumerable over all descendants
        public IEnumerable DescendantNodes() {
            return GetDescendantNodes(false); 
        }
 
        ///  
        /// Returns the descendant s of this .  Note this method will
        /// not return itself in the resulting IEnumerable.  See  if you 
        /// need to include the current  in the results.
        /// 
        /// 
        ///  
        /// An IEnumerable of  with all of the descendants below this  in the XML tree.
        ///  
        public IEnumerable Descendants() { 
            return GetDescendants(null, false);
        } 

        /// 
        /// Returns the Descendant s with the passed in  as an IEnumerable
        /// of XElement. 
        /// 
        /// The  to match against descendant s. 
        /// An  of  
        public IEnumerable Descendants(XName name) {
            return name != null ? GetDescendants(name, false) : XElement.EmptySequence; 
        }

        /// 
        /// Returns the child element with this  or null if there is no child element 
        /// with a matching .
        ///  
        ///  
        /// 
        /// The  to match against this s child elements. 
        /// 
        /// 
        /// An  child that matches the  passed in, or null.
        ///  
        public XElement Element(XName name) {
            XNode n = content as XNode; 
            if (n != null) { 
                do {
                    n = n.next; 
                    XElement e = n as XElement;
                    if (e != null && e.name == name) return e;
                } while (n != content);
            } 
            return null;
        } 
 
        ///
        /// Returns the child s of this . 
        /// 
        /// 
        /// Returns all of the child elements of this .
        ///  
        /// 
        /// An  over all of this 's child s. 
        ///  
        public IEnumerable Elements() {
            return GetElements(null); 
        }

        /// 
        /// Returns the child elements of this  that match the  passed in. 
        /// 
        ///  
        /// The  to match against the  children of this . 
        /// 
        ///  
        /// An  of  children of this  that have
        /// a matching .
        /// 
        public IEnumerable Elements(XName name) { 
            return name != null ? GetElements(name) : XElement.EmptySequence;
        } 
 
        ///
        /// Returns the content of this .  Note that the content does not 
        /// include s.
        /// 
        /// 
        ///  
        /// Returns the content of this  as an  of .  Note
        /// that the content does not include s. 
        ///  
        /// 
        /// The contents of this  
        public IEnumerable Nodes() {
            XNode n = LastNode;
            if (n != null) {
                do { 
                    n = n.next;
                    yield return n; 
                } while (n.parent == this && n != content); 
            }
        } 

        /// 
        /// Removes the nodes from this .  Note this
        /// methods does not remove attributes.  See . 
        /// 
        ///  
        public void RemoveNodes() { 
            if (SkipNotify()) {
                RemoveNodesSkipNotify(); 
                return;
            }
            while (content != null) {
                string s = content as string; 
                if (s != null) {
                    if (s.Length > 0) { 
                        ConvertTextToNode(); 
                    }
                    else { 
                        if (this is XElement) {
                            // Change in the serialization of an empty element:
                            // from start/end tag pair to empty tag
                            NotifyChanging(this, XObjectChangeEventArgs.Value); 
                            if ((object)s != (object)content) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                            content = null; 
                            NotifyChanged(this, XObjectChangeEventArgs.Value); 
                        }
                        else { 
                            content = null;
                        }
                    }
                } 
                XNode last = content as XNode;
                if (last != null) { 
                    XNode n = last.next; 
                    NotifyChanging(n, XObjectChangeEventArgs.Remove);
                    if (last != content || n != last.next) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
                    if (n != last) {
                        last.next = n.next;
                    }
                    else { 
                        content = null;
                    } 
                    n.parent = null; 
                    n.next = null;
                    NotifyChanged(n, XObjectChangeEventArgs.Remove); 
                }
            }
        }
 
        /// 
        /// Replaces the children nodes of this document or element with the specified content. The 
        /// content can be simple content, a collection of content objects, a parameter 
        /// list of content objects, or null.
        ///  
        /// 
        /// Replaces the children nodes of this document or element with the specified content.
        /// 
        ///  
        /// A content object containing simple content or a collection of content objects
        /// that replace the children nodes. 
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        /// 
        public void ReplaceNodes(object content) {
            content = GetContentSnapshot(content); 
            RemoveNodes();
            Add(content); 
        } 

        ///  
        /// Replaces the children nodes of this document or element with the specified content.
        /// 
        /// 
        /// A parameter list of content objects. 
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        public void ReplaceNodes(params object[] content) {
            ReplaceNodes((object)content);
        }
 
        internal virtual void AddAttribute(XAttribute a) {
        } 
 
        internal virtual void AddAttributeSkipNotify(XAttribute a) {
        } 

        internal void AddContentSkipNotify(object content) {
            if (content == null) return;
            XNode n = content as XNode; 
            if (n != null) {
                AddNodeSkipNotify(n); 
                return; 
            }
            string s = content as string; 
            if (s != null) {
                AddStringSkipNotify(s);
                return;
            } 
            XAttribute a = content as XAttribute;
            if (a != null) { 
                AddAttributeSkipNotify(a); 
                return;
            } 
            XStreamingElement x = content as XStreamingElement;
            if (x != null) {
                AddNodeSkipNotify(new XElement(x));
                return; 
            }
            object[] o = content as object[]; 
            if (o != null) { 
                foreach (object obj in o) AddContentSkipNotify(obj);
                return; 
            }
            IEnumerable e = content as IEnumerable;
            if (e != null) {
                foreach (object obj in e) AddContentSkipNotify(obj); 
                return;
            } 
            AddStringSkipNotify(GetStringValue(content)); 
        }
 
        internal void AddNode(XNode n) {
            ValidateNode(n, this);
            if (n.parent != null) {
                n = n.CloneNode(); 
            }
            else { 
                XNode p = this; 
                while (p.parent != null) p = p.parent;
                if (n == p) n = n.CloneNode(); 
            }
            ConvertTextToNode();
            AppendNode(n);
        } 

        internal void AddNodeSkipNotify(XNode n) { 
            ValidateNode(n, this); 
            if (n.parent != null) {
                n = n.CloneNode(); 
            }
            else {
                XNode p = this;
                while (p.parent != null) p = p.parent; 
                if (n == p) n = n.CloneNode();
            } 
            ConvertTextToNode(); 
            AppendNodeSkipNotify(n);
        } 

        internal void AddString(string s) {
            ValidateString(s);
            if (content == null) { 
                if (s.Length > 0) {
                    AppendNode(new XText(s)); 
                } 
                else {
                    if (this is XElement) { 
                        // Change in the serialization of an empty element:
                        // from empty tag to start/end tag pair
                        NotifyChanging(this, XObjectChangeEventArgs.Value);
                        if (content != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
                        content = s;
                        NotifyChanged(this, XObjectChangeEventArgs.Value); 
                    } 
                    else {
                        content = s; 
                    }
                }
            }
            else if (s.Length > 0) { 
                ConvertTextToNode();
                XText tn = content as XText; 
                if (tn != null && !(tn is XCData)) { 
                    tn.Value += s;
                } 
                else {
                    AppendNode(new XText(s));
                }
            } 
        }
 
        internal void AddStringSkipNotify(string s) { 
            ValidateString(s);
            if (content == null) { 
                content = s;
            }
            else if (s.Length > 0) {
                if (content is string) { 
                    content = (string)content + s;
                } 
                else { 
                    XText tn = content as XText;
                    if (tn != null && !(tn is XCData)) { 
                        tn.text += s;
                    }
                    else {
                        AppendNodeSkipNotify(new XText(s)); 
                    }
                } 
            } 
        }
 
        internal void AppendNode(XNode n) {
            bool notify = NotifyChanging(n, XObjectChangeEventArgs.Add);
            if (n.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            AppendNodeSkipNotify(n); 
            if (notify) NotifyChanged(n, XObjectChangeEventArgs.Add);
        } 
 
        internal void AppendNodeSkipNotify(XNode n) {
            n.parent = this; 
            if (content == null || content is string) {
                n.next = n;
            }
            else { 
                XNode x = (XNode)content;
                n.next = x.next; 
                x.next = n; 
            }
            content = n; 
        }

        internal override void AppendText(StringBuilder sb) {
            string s = content as string; 
            if (s != null) {
                sb.Append(s); 
            } 
            else {
                XNode n = (XNode)content; 
                if (n != null) {
                    do {
                        n = n.next;
                        n.AppendText(sb); 
                    } while (n != content);
                } 
            } 
        }
 
        string GetTextOnly() {
            if (content == null) return null;
            string s = content as string;
            if (s == null) { 
                XNode n = (XNode)content;
                do { 
                    n = n.next; 
                    if (n.NodeType != XmlNodeType.Text) return null;
                    s += ((XText)n).Value; 
                } while (n != content);
            }
            return s;
        } 

        string CollectText(ref XNode n) { 
            string s = ""; 
            while (n != null && n.NodeType == XmlNodeType.Text) {
                s += ((XText)n).Value; 
                n = n != content ? n.next : null;
            }
            return s;
        } 

        internal bool ContentsEqual(XContainer e) { 
            if (content == e.content) return true; 
            string s = GetTextOnly();
            if (s != null) return s == e.GetTextOnly(); 
            XNode n1 = content as XNode;
            XNode n2 = e.content as XNode;
            if (n1 != null && n2 != null) {
                n1 = n1.next; 
                n2 = n2.next;
                while (true) { 
                    if (CollectText(ref n1) != e.CollectText(ref n2)) break; 
                    if (n1 == null && n2 == null) return true;
                    if (n1 == null || n2 == null || !n1.DeepEquals(n2)) break; 
                    n1 = n1 != content ? n1.next : null;
                    n2 = n2 != e.content ? n2.next : null;
                }
            } 
            return false;
        } 
 
        internal int ContentsHashCode() {
            string s = GetTextOnly(); 
            if (s != null) return s.GetHashCode();
            int h = 0;
            XNode n = content as XNode;
            if (n != null) { 
                do {
                    n = n.next; 
                    string text = CollectText(ref n); 
                    if (text.Length > 0) {
                        h ^= text.GetHashCode(); 
                    }
                    if (n == null) break;
                    h ^= n.GetDeepHashCode();
                } while (n != content); 
            }
            return h; 
        } 

        internal void ConvertTextToNode() { 
            string s = content as string;
            if (s != null && s.Length > 0) {
                XText t = new XText(s);
                t.parent = this; 
                t.next = t;
                content = t; 
            } 
        }
 
        internal static string GetDateTimeString(DateTime value) {
            return XmlConvert.ToString(value, XmlDateTimeSerializationMode.RoundtripKind);
        }
 
        internal IEnumerable GetDescendantNodes(bool self) {
            if (self) yield return this; 
            XNode n = this; 
            while (true) {
                XContainer c = n as XContainer; 
                XNode first;
                if (c != null && (first = c.FirstNode) != null) {
                    n = first;
                } 
                else {
                    while (n != null && n != this && n == n.parent.content) n = n.parent; 
                    if (n == null || n == this) break; 
                    n = n.next;
                } 
                yield return n;
            }
        }
 
        internal IEnumerable GetDescendants(XName name, bool self) {
            if (self) { 
                XElement e = (XElement)this; 
                if (name == null || e.name == name) yield return e;
            } 
            XNode n = this;
            XContainer c = this;
            while (true) {
                if (c != null && c.content is XNode) { 
                    n = ((XNode)c.content).next;
                } 
                else { 
                    while (n != this && n == n.parent.content) n = n.parent;
                    if (n == this) break; 
                    n = n.next;
                }
                XElement e = n as XElement;
                if (e != null && (name == null || e.name == name)) yield return e; 
                c = e;
            } 
        } 

        IEnumerable GetElements(XName name) { 
            XNode n = content as XNode;
            if (n != null) {
                do {
                    n = n.next; 
                    XElement e = n as XElement;
                    if (e != null && (name == null || e.name == name)) yield return e; 
                } while (n.parent == this && n != content); 
            }
        } 

        internal static string GetStringValue(object value) {
            string s;
            if (value is string) { 
                s = (string)value;
            } 
            else if (value is double) { 
                s = XmlConvert.ToString((double)value);
            } 
            else if (value is float) {
                s = XmlConvert.ToString((float)value);
            }
            else if (value is decimal) { 
                s = XmlConvert.ToString((decimal)value);
            } 
            else if (value is bool) { 
                s = XmlConvert.ToString((bool)value);
            } 
            else if (value is DateTime) {
                s = GetDateTimeString((DateTime)value);
            }
            else if (value is DateTimeOffset) { 
                s = XmlConvert.ToString((DateTimeOffset)value);
            } 
            else if (value is TimeSpan) { 
                s = XmlConvert.ToString((TimeSpan)value);
            } 
            else if (value is XObject) {
                throw new ArgumentException(Res.GetString(Res.Argument_XObjectValue));
            }
            else { 
                s = value.ToString();
            } 
            if (s == null) throw new ArgumentException(Res.GetString(Res.Argument_ConvertToString)); 
            return s;
        } 

        internal void ReadContentFrom(XmlReader r) {
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive));
            XContainer c = this; 
            NamespaceCache eCache = new NamespaceCache();
            NamespaceCache aCache = new NamespaceCache(); 
            do { 
                switch (r.NodeType) {
                    case XmlNodeType.Element: 
                        XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
                        if (r.MoveToFirstAttribute()) {
                            do {
                                e.AppendAttributeSkipNotify(new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value)); 
                            } while (r.MoveToNextAttribute());
                            r.MoveToElement(); 
                        } 
                        c.AddNodeSkipNotify(e);
                        if (!r.IsEmptyElement) { 
                            c = e;
                        }
                        break;
                    case XmlNodeType.EndElement: 
                        if (c.content == null) {
                            c.content = string.Empty; 
                        } 
                        if (c == this) return;
                        c = c.parent; 
                        break;
                    case XmlNodeType.Text:
                    case XmlNodeType.SignificantWhitespace:
                    case XmlNodeType.Whitespace: 
                        c.AddStringSkipNotify(r.Value);
                        break; 
                    case XmlNodeType.CDATA: 
                        c.AddNodeSkipNotify(new XCData(r.Value));
                        break; 
                    case XmlNodeType.Comment:
                        c.AddNodeSkipNotify(new XComment(r.Value));
                        break;
                    case XmlNodeType.ProcessingInstruction: 
                        c.AddNodeSkipNotify(new XProcessingInstruction(r.Name, r.Value));
                        break; 
                    case XmlNodeType.DocumentType: 
                        c.AddNodeSkipNotify(new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value));
                        break; 
                    case XmlNodeType.EntityReference:
                        if (!r.CanResolveEntity) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnresolvedEntityReference));
                        r.ResolveEntity();
                        break; 
                    case XmlNodeType.EndEntity:
                        break; 
                    default: 
                        throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, r.NodeType));
                } 
            } while (r.Read());
        }

        internal void ReadContentFrom(XmlReader r, LoadOptions o) { 
            if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == 0) {
                ReadContentFrom(r); 
                return; 
            }
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive)); 
            XContainer c = this;
            XNode n = null;
            NamespaceCache eCache = new NamespaceCache();
            NamespaceCache aCache = new NamespaceCache(); 
            string baseUri = (o & LoadOptions.SetBaseUri) != 0 ? r.BaseURI : null;
            IXmlLineInfo li = (o & LoadOptions.SetLineInfo) != 0 ? r as IXmlLineInfo : null; 
            do { 
                string uri = r.BaseURI;
                switch (r.NodeType) { 
                    case XmlNodeType.Element:
                        XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
                        if (baseUri != null && baseUri != uri) {
                            e.SetBaseUri(uri); 
                        }
                        if (li != null && li.HasLineInfo()) { 
                            e.SetLineInfo(li.LineNumber, li.LinePosition); 
                        }
                        if (r.MoveToFirstAttribute()) { 
                            do {
                                XAttribute a = new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
                                if (li != null && li.HasLineInfo()) {
                                    a.SetLineInfo(li.LineNumber, li.LinePosition); 
                                }
                                e.AppendAttributeSkipNotify(a); 
                            } while (r.MoveToNextAttribute()); 
                            r.MoveToElement();
                        } 
                        c.AddNodeSkipNotify(e);
                        if (!r.IsEmptyElement) {
                            c = e;
                            if (baseUri != null) { 
                                baseUri = uri;
                            } 
                        } 
                        break;
                    case XmlNodeType.EndElement: 
                        if (c.content == null) {
                            c.content = string.Empty;
                        }
                        if (c == this) return; 
                        if (baseUri != null && c.HasBaseUri) {
                            baseUri = c.parent.BaseUri; 
                        } 
                        c = c.parent;
                        break; 
                    case XmlNodeType.Text:
                    case XmlNodeType.SignificantWhitespace:
                    case XmlNodeType.Whitespace:
                        if ((baseUri != null && baseUri != uri) || 
                            (li != null && li.HasLineInfo())) {
                            n = new XText(r.Value); 
                        } 
                        else {
                            c.AddStringSkipNotify(r.Value); 
                        }
                        break;
                    case XmlNodeType.CDATA:
                        n = new XCData(r.Value); 
                        break;
                    case XmlNodeType.Comment: 
                        n = new XComment(r.Value); 
                        break;
                    case XmlNodeType.ProcessingInstruction: 
                        n = new XProcessingInstruction(r.Name, r.Value);
                        break;
                    case XmlNodeType.DocumentType:
                        n = new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value); 
                        break;
                    case XmlNodeType.EntityReference: 
                        if (!r.CanResolveEntity) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnresolvedEntityReference)); 
                        r.ResolveEntity();
                        break; 
                    case XmlNodeType.EndEntity:
                        break;
                    default:
                        throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, r.NodeType)); 
                }
                if (n != null) { 
                    if (baseUri != null && baseUri != uri) { 
                        n.SetBaseUri(uri);
                    } 
                    if (li != null && li.HasLineInfo()) {
                        n.SetLineInfo(li.LineNumber, li.LinePosition);
                    }
                    c.AddNodeSkipNotify(n); 
                    n = null;
                } 
            } while (r.Read()); 
        }
 
        internal void RemoveNode(XNode n) {
            bool notify = NotifyChanging(n, XObjectChangeEventArgs.Remove);
            if (n.parent != this) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            XNode p = (XNode)content; 
            while (p.next != n) p = p.next;
            if (p == n) { 
                content = null; 
            }
            else { 
                if (content == n) content = p;
                p.next = n.next;
            }
            n.parent = null; 
            n.next = null;
            if (notify) NotifyChanged(n, XObjectChangeEventArgs.Remove); 
        } 

        void RemoveNodesSkipNotify() { 
            XNode n = content as XNode;
            if (n != null) {
                do {
                    XNode next = n.next; 
                    n.parent = null;
                    n.next = null; 
                    n = next; 
                } while (n != content);
            } 
            content = null;
        }

        // Validate insertion of the given node. previous is the node after which insertion 
        // will occur. previous == null means at beginning, previous == this means at end.
        internal virtual void ValidateNode(XNode node, XNode previous) { 
        } 

        internal virtual void ValidateString(string s) { 
        }

        internal void WriteContentTo(XmlWriter writer) {
            if (content != null) { 
                if (content is string) {
                    if (this is XDocument) { 
                        writer.WriteWhitespace((string)content); 
                    }
                    else { 
                        writer.WriteString((string)content);
                    }
                }
                else { 
                    XNode n = (XNode)content;
                    do { 
                        n = n.next; 
                        n.WriteTo(writer);
                    } while (n != content); 
                }
            }
        }
 
        static void AddContentToList(List list, object content) {
            IEnumerable e = content is string ? null : content as IEnumerable; 
            if (e == null) { 
                list.Add(content);
            } 
            else {
                foreach (object obj in e) {
                    if (obj != null) AddContentToList(list, obj);
                } 
            }
        } 
 
        static internal object GetContentSnapshot(object content) {
            if (content is string || !(content is IEnumerable)) return content; 
            List list = new List();
            AddContentToList(list, content);
            return list;
        } 
    }
 
    internal struct Inserter 
    {
        XContainer parent; 
        XNode previous;
        string text;

        public Inserter(XContainer parent, XNode anchor) { 
            this.parent = parent;
            this.previous = anchor; 
            this.text = null; 
        }
 
        public void Add(object content) {
            AddContent(content);
            if (text != null) {
                if (parent.content == null) { 
                    if (parent.SkipNotify()) {
                        parent.content = text; 
                    } 
                    else {
                        if (text.Length > 0) { 
                            InsertNode(new XText(text));
                        }
                        else {
                            if (parent is XElement) { 
                                // Change in the serialization of an empty element:
                                // from empty tag to start/end tag pair 
                                parent.NotifyChanging(parent, XObjectChangeEventArgs.Value); 
                                if (parent.content != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                                parent.content = text; 
                                parent.NotifyChanged(parent, XObjectChangeEventArgs.Value);
                            }
                            else {
                                parent.content = text; 
                            }
                        } 
                    } 
                }
                else if (text.Length > 0) { 
                    if (previous is XText && !(previous is XCData)) {
                        ((XText)previous).Value += text;
                    }
                    else { 
                        parent.ConvertTextToNode();
                        InsertNode(new XText(text)); 
                    } 
                }
            } 
        }

        void AddContent(object content) {
            if (content == null) return; 
            XNode n = content as XNode;
            if (n != null) { 
                AddNode(n); 
                return;
            } 
            string s = content as string;
            if (s != null) {
                AddString(s);
                return; 
            }
            XStreamingElement x = content as XStreamingElement; 
            if (x != null) { 
                AddNode(new XElement(x));
                return; 
            }
            object[] o = content as object[];
            if (o != null) {
                foreach (object obj in o) AddContent(obj); 
                return;
            } 
            IEnumerable e = content as IEnumerable; 
            if (e != null) {
                foreach (object obj in e) AddContent(obj); 
                return;
            }
            if (content is XAttribute) throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
            AddString(XContainer.GetStringValue(content)); 
        }
 
        void AddNode(XNode n) { 
            parent.ValidateNode(n, previous);
            if (n.parent != null) { 
                n = n.CloneNode();
            }
            else {
                XNode p = parent; 
                while (p.parent != null) p = p.parent;
                if (n == p) n = n.CloneNode(); 
            } 
            parent.ConvertTextToNode();
            if (text != null) { 
                if (text.Length > 0) {
                    if (previous is XText && !(previous is XCData)) {
                        ((XText)previous).Value += text;
                    } 
                    else {
                        InsertNode(new XText(text)); 
                    } 
                }
                text = null; 
            }
            InsertNode(n);
        }
 
        void AddString(string s) {
            parent.ValidateString(s); 
            text += s; 
        }
 
        // Prepends if previous == null, otherwise inserts after previous
        void InsertNode(XNode n) {
            bool notify = parent.NotifyChanging(n, XObjectChangeEventArgs.Add);
            if (n.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
            n.parent = parent;
            if (parent.content == null || parent.content is string) { 
                n.next = n; 
                parent.content = n;
            } 
            else if (previous == null) {
                XNode last = (XNode)parent.content;
                n.next = last.next;
                last.next = n; 
            }
            else { 
                n.next = previous.next; 
                previous.next = n;
                if (parent.content == previous) parent.content = n; 
            }
            previous = n;
            if (notify) parent.NotifyChanged(n, XObjectChangeEventArgs.Add);
        } 
    }
 
    internal struct NamespaceCache 
    {
        XNamespace ns; 
        string namespaceName;

        public XNamespace Get(string namespaceName) {
            if ((object)namespaceName == (object)this.namespaceName) return this.ns; 
            this.namespaceName = namespaceName;
            this.ns = XNamespace.Get(namespaceName); 
            return this.ns; 
        }
    } 

    /// 
    /// Represents an XML element.
    ///  
    /// 
    /// An element has an , optionally one or more attributes, 
    /// and can optionally contain content (see . 
    /// An  can contain the following types of content:
    ///    
    ///     string (Text content)
    ///     
    ///     
    ///      
    ///   
    ///  
    [XmlSchemaProvider(null, IsAny=true)] 
    [System.ComponentModel.TypeDescriptionProvider(typeof(ComponentModel.XTypeDescriptionProvider))]
    public class XElement : XContainer, IXmlSerializable 
    {
        static IEnumerable emptySequence;

        ///  
        /// Gets an empty collection of elements.
        ///  
        public static IEnumerable EmptySequence { 
            get {
                if (emptySequence == null) emptySequence = new XElement[0]; 
                return emptySequence;
            }
        }
 
        internal XName name;
        internal XAttribute lastAttr; 
 
        /// 
        /// Initializes a new instance of the XElement class with the specified name. 
        /// 
        /// 
        /// The name of the element.
        ///  
        public XElement(XName name) {
            if (name == null) throw new ArgumentNullException("name"); 
            this.name = name; 
        }
 
        /// 
        /// Initializes a new instance of the XElement class with the specified name and content.
        /// 
        ///  
        /// The element name.
        ///  
        /// The initial contents of the element. 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        /// 
        public XElement(XName name, object content) : this(name) {
            AddContentSkipNotify(content); 
        }
 
        ///  
        /// Initializes a new instance of the XElement class with the specified name and content.
        ///  
        /// 
        /// The element name.
        /// 
        ///  
        /// The initial content of the element.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public XElement(XName name, params object[] content) : this(name, (object)content) { }

        ///  
        /// Initializes a new instance of the XElement class from another XElement object.
        ///  
        ///  
        /// Another element that will be copied to this element.
        ///  
        /// 
        /// This constructor makes a deep copy from one element to another.
        /// 
        public XElement(XElement other) : base(other) { 
            this.name = other.name;
            XAttribute a = other.lastAttr; 
            if (a != null) { 
                do {
                    a = a.next; 
                    AppendAttributeSkipNotify(new XAttribute(a));
                } while (a != other.lastAttr);
            }
        } 

        ///  
        /// Initializes an XElement object from an  object. 
        /// 
        ///  
        /// The  object whose value will be used
        /// to initialise the new element.
        /// 
        public XElement(XStreamingElement other) { 
            if (other == null) throw new ArgumentNullException("other");
            name = other.name; 
            AddContentSkipNotify(other.content); 
        }
 
        internal XElement() : this("default") {
        }

        internal XElement(XmlReader r) : this(r, LoadOptions.None) { 
        }
 
        internal XElement(XmlReader r, LoadOptions o) { 
            ReadElementFrom(r, o);
        } 

        /// 
        /// Gets the first attribute of an element.
        ///  
        public XAttribute FirstAttribute {
            get { return lastAttr != null ? lastAttr.next : null; } 
        } 

        ///  
        /// Gets a value indicating whether the element as at least one attribute.
        /// 
        public bool HasAttributes {
            get { return lastAttr != null; } 
        }
 
        ///  
        /// Gets a value indicating whether the element has at least one child element.
        ///  
        public bool HasElements {
            get {
                XNode n = content as XNode;
                if (n != null) { 
                    do {
                        if (n is XElement) return true; 
                        n = n.next; 
                    } while (n != content);
                } 
                return false;
            }
        }
 
        /// 
        /// Gets a value indicating whether the element contains no content. 
        ///  
        public bool IsEmpty {
            get { return content == null; } 
        }

        /// 
        /// Gets the last attribute of an element. 
        /// 
        public XAttribute LastAttribute { 
            get { return lastAttr; } 
        }
 
        /// 
        /// Gets the name of this element.
        /// 
        public XName Name { 
            get {
                return name; 
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                name = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name);
            } 
        }
 
        ///  
        /// Gets the node type for this node.
        ///  
        /// 
        /// This property will always return XmlNodeType.Text.
        /// 
        public override XmlNodeType NodeType { 
            get {
                return XmlNodeType.Element; 
            } 
        }
 
        /// 
        /// Gets the text contents of this element.
        /// 
        ///  
        /// If there is text content interspersed with nodes (mixed content) then the text content
        /// will be concatenated and returned. 
        ///  
        public string Value {
            get { 
                if (content == null) return string.Empty;
                string s = content as string;
                if (s != null) return s;
                StringBuilder sb = new StringBuilder(); 
                AppendText(sb);
                return sb.ToString(); 
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                RemoveNodes();
                Add(value);
            }
        } 

        ///  
        /// Returns this  and all of it's ancestors up 
        /// to the root node.  Optionally an  can be passed
        /// in to target a specific ancestor(s). 
        /// 
        /// 
        /// 
        /// Returns this  and all of it's ancestors up to 
        /// the root node.
        ///  
        ///  
        /// 
        /// An  of  containing all of 
        /// this 's ancestors up to the root node (including
        /// this .
        /// 
        public IEnumerable AncestorsAndSelf() { 
            return GetAncestors(null, true);
        } 
 
        /// 
        /// Returns the ancestor(s) of this  with the matching 
        /// . If this 's 
        /// matches the  passed in then it will be invluded in the
        /// resulting  or .
        ///  
        /// 
        ///  
        /// The  of the target ancestor. 
        /// 
        ///  
        /// An  of  containing the
        /// ancestors of this  with a matching .
        /// 
        public IEnumerable AncestorsAndSelf(XName name) { 
            return name != null ? GetAncestors(name, true) : XElement.EmptySequence;
        } 
 
        /// 
        /// Returns the  associated with this  that has this 
        /// .
        /// 
        /// 
        /// The  of the  to get. 
        /// 
        ///  
        /// The  with the  passed in.  If there is no  
        /// with this  then null is returned.
        ///  
        public XAttribute Attribute(XName name) {
            XAttribute a = lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    if (a.name == name) return a; 
                } while (a != lastAttr); 
            }
            return null; 
        }

        /// 
        /// Returns the  associated with this .  Optionally 
        /// an  can be given to target a specific (s).
        ///  
        ///  
        /// Returns all of the s associated with this .
        ///  
        /// 
        /// 
        /// An  of  containing all of the s
        /// associated with this . 
        /// 
        public IEnumerable Attributes() { 
            return GetAttributes(null); 
        }
 
        /// 
        /// Returns the (s) associated with this  that has the passed
        /// in .
        ///  
        /// 
        ///  
        /// The  of the targeted . 
        /// 
        ///  
        /// The (s) with the matching
        /// 
        public IEnumerable Attributes(XName name) {
            return name != null ? GetAttributes(name) : XAttribute.EmptySequence; 
        }
 
        ///  
        /// Get the self and descendant nodes for an 
        ///  
        /// 
        public IEnumerable DescendantNodesAndSelf() {
            return GetDescendantNodes(true);
        } 

        ///  
        /// Returns this  and all of it's descendants.  Overloads allow 
        /// specification of a type of descendant to return, or a specific 
        /// of a descendant  to match. 
        /// 
        /// 
        /// Returns this  and all of it's descendant s
        /// as an  of . 
        /// 
        ///  
        ///  
        /// An  of  containing this 
        /// and all of it's descendants. 
        /// 
        public IEnumerable DescendantsAndSelf() {
            return GetDescendants(null, true);
        } 

        ///  
        /// Returns the descendants of this  that have a matching  
        /// to the one passed in, including, potentially, this .
        ///  
        /// 
        /// 
        /// The  of the descendant  that is being targeted.
        ///  
        /// 
        /// An  of  containing all of the descendant 
        /// s that have this . 
        /// 
        public IEnumerable DescendantsAndSelf(XName name) { 
            return name != null ? GetDescendants(name, true) : XElement.EmptySequence;
        }

        ///  
        /// Returns the default  of an 
        ///  
        public XNamespace GetDefaultNamespace() { 
            string namespaceName = GetNamespaceOfPrefixInScope("xmlns", null);
            return namespaceName != null ? XNamespace.Get(namespaceName) : XNamespace.None; 
        }

        /// 
        /// Get the namespace associated with a particular prefix for this  
        /// in its document context.
        ///  
        /// The namespace prefix to look up 
        /// An  for the namespace bound to the prefix
        public XNamespace GetNamespaceOfPrefix(string prefix) { 
            if (prefix == null) throw new ArgumentNullException("prefix");
            if (prefix.Length == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidPrefix, prefix));
            if (prefix == "xmlns") return XNamespace.Xmlns;
            string namespaceName = GetNamespaceOfPrefixInScope(prefix, null); 
            if (namespaceName != null) return XNamespace.Get(namespaceName);
            if (prefix == "xml") return XNamespace.Xml; 
            return null; 
        }
 
        /// 
        /// Get the prefix associated with a namespace for an element in its context.
        /// 
        /// The  for which to get a prefix 
        /// The namespace prefix string
        public string GetPrefixOfNamespace(XNamespace ns) { 
            if (ns == null) throw new ArgumentNullException("ns"); 
            string namespaceName = ns.NamespaceName;
            bool hasInScopeNamespace = false; 
            XElement e = this;
            do {
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    bool hasLocalNamespace = false;
                    do { 
                        a = a.next; 
                        if (a.IsNamespaceDeclaration) {
                            if (a.Value == namespaceName) { 
                                if (a.Name.NamespaceName.Length != 0 &&
                                    (!hasInScopeNamespace ||
                                     GetNamespaceOfPrefixInScope(a.Name.LocalName, e) == null)) {
                                    return a.Name.LocalName; 
                                }
                            } 
                            hasLocalNamespace = true; 
                        }
                    } 
                    while (a != e.lastAttr);
                    hasInScopeNamespace |= hasLocalNamespace;
                }
                e = e.parent as XElement; 
            }
            while (e != null); 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) { 
                if (!hasInScopeNamespace || GetNamespaceOfPrefixInScope("xml", null) == null) return "xml";
            } 
            else if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) {
                return "xmlns";
            }
            return null; 
        }
 
        ///  
        /// The Load method provides multiple strategies for creating a new
        ///  and initializing it from a data source containing 
        /// raw XML.  Load from a file (passing in a URI to the file), an
        /// , a , or an
        /// .  Note:  Use 
        /// to create an  from a string containing XML. 
        /// 
        ///  
        ///  
        /// 
        /// Create a new  based on the contents of the file 
        /// referenced by the URI parameter passed in.  Note: Use
        ///  to create an  from
        /// a string containing XML.
        ///  
        /// 
        ///  
        ///  
        /// 
        /// This method uses the  constructor to create 
        /// an  to read the raw XML into the underlying
        /// XML tree.
        /// 
        ///  
        /// A URI string referencing the file to load into a new .
        ///  
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed in uri parameter. 
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Back-compat with System.Xml.")]
        public static XElement Load(string uri) {
            return Load(uri, LoadOptions.None); 
        }
 
        ///  
        /// Create a new  based on the contents of the file
        /// referenced by the URI parameter passed in.  Optionally, whitespace can be preserved. 
        /// 
        /// 
        /// 
        ///  
        /// This method uses the  constructor to create
        /// an  to read the raw XML into an underlying 
        /// XML tree. If LoadOptions.PreserveWhitespace is enabled then 
        /// the  property 
        /// is set to . 
        /// 
        /// 
        /// A string representing the URI of the file to be loaded into a new .
        ///  
        /// 
        /// A set of . 
        ///  
        /// 
        /// An  initialized with the contents of the file referenced 
        /// in the passed uri parameter.  If LoadOptions.PreserveWhitespace is enabled then
        /// significant whitespace will be preserved.
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Back-compat with System.Xml.")] 
        public static XElement Load(string uri, LoadOptions options) {
            XmlReaderSettings rs = GetXmlReaderSettings(options); 
            using (XmlReader r = XmlReader.Create(uri, rs)) { 
                return Load(r, options);
            } 
        }

        /// 
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.
        ///  
        ///  
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        /// 
        /// A new  containing the contents of the passed in
        /// . 
        /// 
        public static XElement Load(TextReader textReader) { 
            return Load(textReader, LoadOptions.None); 
        }
 
        /// 
        /// Create a new  and initialize its underlying XML tree using
        /// the passed  parameter.  Optionally whitespace handling
        /// can be preserved. 
        /// 
        ///  
        /// If LoadOptions.PreserveWhitespace is enabled then 
        /// the  property 
        /// is set to . 
        /// 
        /// 
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        ///  
        /// A set of . 
        /// 
        ///  
        /// A new  containing the contents of the passed in
        /// .
        /// 
        public static XElement Load(TextReader textReader, LoadOptions options) { 
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(textReader, rs)) { 
                return Load(r, options); 
            }
        } 

        /// 
        /// Create a new  containing the contents of the
        /// passed in . 
        /// 
        ///  
        /// An  containing the XML to be read into the new 
        /// .
        ///  
        /// 
        /// A new  containing the contents of the passed
        /// in .
        ///  
        public static XElement Load(XmlReader reader) {
            return Load(reader, LoadOptions.None); 
        } 

        ///  
        /// Create a new  containing the contents of the
        /// passed in .
        /// 
        ///  
        /// An  containing the XML to be read into the new
        /// . 
        ///  
        /// 
        /// A set of . 
        /// 
        /// 
        /// A new  containing the contents of the passed
        /// in . 
        /// 
        public static XElement Load(XmlReader reader, LoadOptions options) { 
            if (reader == null) throw new ArgumentNullException("reader"); 
            if (reader.MoveToContent() != XmlNodeType.Element) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedNodeType, XmlNodeType.Element, reader.NodeType));
            XElement e = new XElement(reader, options); 
            reader.MoveToContent();
            if (!reader.EOF) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedEndOfFile));
            return e;
        } 

        ///  
        /// Parses a string containing XML into an .  Optionally 
        /// whitespace can be preserved.
        ///  
        /// 
        /// Parses a string containing XML into an .
        /// 
        ///  
        /// The XML must contain only one root node.
        ///  
        ///  
        /// A string containing the XML to parse into an .
        ///  
        /// 
        /// An  created from the XML string passed in.
        /// 
        public static XElement Parse(string text) { 
            return Parse(text, LoadOptions.None);
        } 
 
        /// 
        /// Parses a string containing XML into an  and 
        /// optionally preserves the Whitepspace.  See .
        /// 
        /// 
        ///  
        /// 
        /// The XML must contain only one root node. 
        ///  
        /// If LoadOptions.PreserveWhitespace is enabled the underlying
        /// 's 
        /// whitespace handling to significant (see .
        /// 
        /// 
        ///  
        /// 
        /// A string containing the XML to parse into an . 
        ///  
        /// 
        /// A set of . 
        /// 
        /// 
        /// An  created from the XML string passed in.
        ///  
        public static XElement Parse(string text, LoadOptions options) {
            using (StringReader sr = new StringReader(text)) { 
                XmlReaderSettings rs = GetXmlReaderSettings(options); 
                using (XmlReader r = XmlReader.Create(sr, rs)) {
                    return Load(r, options); 
                }
            }
        }
 
        /// 
        /// Removes content and attributes from this . 
        ///  
        /// 
        ///  
        public void RemoveAll() {
            RemoveAttributes();
            RemoveNodes();
        } 

        ///  
        /// Removes that attributes of this . 
        /// 
        ///  
        /// 
        public void RemoveAttributes() {
            if (SkipNotify()) {
                RemoveAttributesSkipNotify(); 
                return;
            } 
            while (lastAttr != null) { 
                XAttribute a = lastAttr.next;
                NotifyChanging(a, XObjectChangeEventArgs.Remove); 
                if (lastAttr == null || a != lastAttr.next) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                if (a != lastAttr) {
                    lastAttr.next = a.next;
                } 
                else {
                    lastAttr = null; 
                } 
                a.parent = null;
                a.next = null; 
                NotifyChanged(a, XObjectChangeEventArgs.Remove);
            }
        }
 
        /// 
        /// Replaces the child nodes and the attributes of this element with the 
        /// specified content. The content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, or null.
        ///  
        /// 
        /// Replaces the children nodes and the attributes of this element with the specified content.
        /// 
        ///  
        /// The content that will replace the child nodes and attributes of this element.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void ReplaceAll(object content) {
            content = GetContentSnapshot(content);
            RemoveAll(); 
            Add(content);
        } 
 
        /// 
        /// Replaces the children nodes and the attributes of this element with the specified content. 
        /// 
        /// 
        /// A parameter list of content objects.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void ReplaceAll(params object[] content) { 
            ReplaceAll((object)content);
        }

        ///  
        /// Replaces the attributes of this element with the specified content.
        /// The content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, or null. 
        /// 
        ///  
        /// Replaces the attributes of this element with the specified content.
        /// 
        /// 
        /// The content that will replace the attributes of this element. 
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        public void ReplaceAttributes(object content) {
            content = GetContentSnapshot(content);
            RemoveAttributes();
            Add(content); 
        }
 
        ///  
        /// Replaces the attributes of this element with the specified content.
        ///  
        /// 
        /// A parameter list of content objects.
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        ///  
        public void ReplaceAttributes(params object[] content) {
            ReplaceAttributes((object)content); 
        }

        ///
        /// Outputs this 's underlying XML tree.  The output can 
        /// be saved to a file, an , a ,
        /// or an .  Optionally whitespace can be preserved. 
        ///  
        /// 
        /// Output this  to a file. 
        /// 
        /// 
        /// The format will be indented by default.  If you want
        /// no indenting then use the SaveOptions version of Save (see 
        /// ) enabling
        /// SaveOptions.DisableFormatting 
        ///  
        /// 
        /// The name of the file to output the XML to. 
        /// 
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None);
        } 

        ///  
        /// Output this  to a file. 
        /// 
        ///  
        /// The name of the file to output the XML to.
        /// 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented. 
        /// 
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = GetXmlWriterSettings(options); 
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) {
                Save(w); 
            }
        }

        ///  
        /// Output this  to the passed in .
        ///  
        ///  
        /// The format will be indented by default.  If you want
        /// no indenting then use the SaveOptions version of Save (see 
        /// ) enabling
        /// SaveOptions.DisableFormatting
        /// 
        ///  
        /// The  to output this  to.
        ///  
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None);
        } 

        /// 
        /// Output this  to a .
        ///  
        /// 
        /// The  to output the XML to. 
        ///  
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented. 
        /// 
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) { 
                Save(w);
            } 
        } 

        ///  
        /// Output this  to an .
        /// 
        /// 
        /// The  to output the XML to. 
        /// 
        public void Save(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteStartDocument();
            WriteTo(writer); 
            writer.WriteEndDocument();
        }

        ///  
        /// Sets the value of an attribute. The value is assigned to the attribute with the given
        /// name. If no attribute with the given name exists, a new attribute is added. If the 
        /// value is null, the attribute with the given name, if any, is deleted. 
        /// 
        ///  
        /// 
        /// 
        /// 
        /// The name of the attribute whose value to change. 
        /// 
        ///  
        /// The value to assign to the attribute. The attribute is deleted if the value is null. 
        /// Otherwise, the value is converted to its string representation and assigned to the
        ///  property of the attribute. 
        /// 
        /// 
        /// Thrown if the value is an instance of .
        ///  
        public void SetAttributeValue(XName name, object value) {
            XAttribute a = Attribute(name); 
            if (value == null) { 
                if (a != null) RemoveAttribute(a);
            } 
            else {
                if (a != null) {
                    a.Value = GetStringValue(value);
                } 
                else {
                    AppendAttribute(new XAttribute(name, value)); 
                } 
            }
        } 

        /// 
        /// Sets the value of a child element. The value is assigned to the first child element
        /// with the given name. If no child element with the given name exists, a new child 
        /// element is added. If the value is null, the first child element with the given name,
        /// if any, is deleted. 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// The name of the child element whose value to change.
        ///  
        /// 
        /// The value to assign to the child element. The child element is deleted if the value 
        /// is null. Otherwise, the value is converted to its string representation and assigned 
        /// to the  property of the child element.
        ///  
        /// 
        /// Thrown if the value is an instance of .
        /// 
        public void SetElementValue(XName name, object value) { 
            XElement e = Element(name);
            if (value == null) { 
                if (e != null) RemoveNode(e); 
            }
            else { 
                if (e != null) {
                    e.Value = GetStringValue(value);
                }
                else { 
                    AddNode(new XElement(name, GetStringValue(value)));
                } 
            } 
        }
 
        /// 
        /// Sets the value of this element.
        /// 
        ///  
        /// 
        ///  
        ///  
        /// The value to assign to this element. The value is converted to its string representation
        /// and assigned to the  property. 
        /// 
        /// 
        /// Thrown if the specified value is null.
        ///  
        public void SetValue(object value) {
            if (value == null) throw new ArgumentNullException("value"); 
            Value = GetStringValue(value); 
        }
 
        /// 
        /// Write this  to the passed in .
        /// 
        ///  
        /// The  to write this  to.
        ///  
        public override void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer");
            new ElementWriter(writer).WriteElement(this); 
        }

        /// 
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// If the  is a subtre (an  
        /// that has  children.  The concatenated string
        /// value of all of the 's text and descendants 
        /// text is returned.
        /// 
        /// 
        /// The  to cast to a string. 
        /// 
        ///  
        /// The content of this  as a . 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator string(XElement element) {
            if (element == null) return null;
            return element.Value; 
        }
 
        ///  
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to .
        /// 
        ///  
        /// The content of this  as a .
        ///  
        ///  
        /// Thrown if the element does not contain a valid boolean value.
        ///  
        /// 
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator bool(XElement element) { 
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToBoolean(element.Value.ToLower(CultureInfo.InvariantCulture));
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        /// 
        /// Thrown if the element does not contain a valid boolean value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator bool?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToBoolean(element.Value.ToLower(CultureInfo.InvariantCulture)); 
        }

        /// 
        /// Cast the value of this  to an . 
        /// 
        ///  
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a .
        /// 
        /// 
        /// Thrown if the element does not contain a valid integer value. 
        /// 
        ///  
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator int(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToInt32(element.Value); 
        }
 
        ///  
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?.
        /// 
        ///  
        /// The content of this  as a ?.
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid integer value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator int?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToInt32(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to an . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid unsigned integer value. 
        /// 
        /// 
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator uint(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToUInt32(element.Value); 
        }

        /// 
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?.
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid unsigned integer value. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator uint?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToUInt32(element.Value);
        }

        ///  
        /// Cast the value of this  to a .
        ///  
        ///  
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a .
        /// 
        ///  
        /// Thrown if the element does not contain a valid long integer value.
        ///  
        ///  
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator long(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToInt64(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid long integer value. 
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator long?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToInt64(element.Value); 
        } 

        ///  
        /// Cast the value of this  to an .
        /// 
        /// 
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a . 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid unsigned long integer value.
        /// 
        /// 
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator ulong(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToUInt64(element.Value);
        }

        ///  
        /// Cast the value of this  to an ?.
        ///  
        ///  
        /// The  to cast to ?.
        ///  
        /// 
        /// The content of this  as a ?.
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid unsigned long integer value.
        ///  
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator ulong?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToUInt64(element.Value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid float value. 
        ///  
        /// 
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator float(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToSingle(element.Value); 
        } 

        ///  
        /// Cast the value of this  to an ?.
        /// 
        /// 
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?. 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid float value.
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator float?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToSingle(element.Value); 
        }
 
        /// 
        /// Cast the value of this  to a .
        /// 
        ///  
        /// The  to cast to .
        ///  
        ///  
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid double value.
        /// 
        ///  
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator double(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToDouble(element.Value);
        }
 
        /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid double value. 
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator double?(XElement element) {
            if (element == null) return null;
            return XmlConvert.ToDouble(element.Value);
        } 

        ///  
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// The  to cast to .
        /// 
        /// 
        /// The content of this  as a . 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid decimal value. 
        /// 
        ///  
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator decimal(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToDecimal(element.Value); 
        }
 
        /// 
        /// Cast the value of this  to an ?.
        /// 
        ///  
        /// The  to cast to ?.
        ///  
        ///  
        /// The content of this  as a ?.
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid decimal value.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator decimal?(XElement element) { 
            if (element == null) return null; 
            return XmlConvert.ToDecimal(element.Value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        /// 
        /// Thrown if the specified element is null. 
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator DateTime(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return DateTime.Parse(element.Value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 

        ///  
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?.
        /// 
        /// 
        /// The content of this  as a ?. 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid  value. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator DateTime?(XElement element) {
            if (element == null) return null;
            return DateTime.Parse(element.Value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind); 
        }
 
        ///  
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to .
        /// 
        ///  
        /// The content of this  as a .
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        /// 
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator DateTimeOffset(XElement element) { 
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToDateTimeOffset(element.Value);
        } 

        /// 
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator DateTimeOffset?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToDateTimeOffset(element.Value); 
        }

        /// 
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a .
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value. 
        /// 
        ///  
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator TimeSpan(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToTimeSpan(element.Value); 
        }
 
        ///  
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?.
        /// 
        ///  
        /// The content of this  as a ?.
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator TimeSpan?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToTimeSpan(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid guid. 
        /// 
        /// 
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator Guid(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToGuid(element.Value); 
        }

        /// 
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?.
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid guid. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator Guid?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToGuid(element.Value);
        }

        ///  
        /// This method is obsolete for the IXmlSerializable contract.
        ///  
        XmlSchema IXmlSerializable.GetSchema() { 
            return null;
        } 

        /// 
        /// Generates a  from its XML respresentation.
        ///  
        /// 
        /// The  stream from which the  
        /// is deserialized. 
        /// 
        void IXmlSerializable.ReadXml(XmlReader reader) { 
            if (reader == null) throw new ArgumentNullException("reader");
            if (parent != null || annotations != null || content != null || lastAttr != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DeserializeInstance));
            if (reader.MoveToContent() != XmlNodeType.Element) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedNodeType, XmlNodeType.Element, reader.NodeType));
            ReadElementFrom(reader, LoadOptions.None); 
        }
 
        ///  
        /// Converts a  into its XML representation.
        ///  
        /// 
        /// The  stream to which the 
        /// is serialized.
        ///  
        void IXmlSerializable.WriteXml(XmlWriter writer) {
            WriteTo(writer); 
        } 

        internal override void AddAttribute(XAttribute a) { 
            if (Attribute(a.Name) != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DuplicateAttribute));
            if (a.parent != null) a = new XAttribute(a);
            AppendAttribute(a);
        } 

        internal override void AddAttributeSkipNotify(XAttribute a) { 
            if (Attribute(a.Name) != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DuplicateAttribute)); 
            if (a.parent != null) a = new XAttribute(a);
            AppendAttributeSkipNotify(a); 
        }

        internal void AppendAttribute(XAttribute a) {
            bool notify = NotifyChanging(a, XObjectChangeEventArgs.Add); 
            if (a.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            AppendAttributeSkipNotify(a); 
            if (notify) NotifyChanged(a, XObjectChangeEventArgs.Add); 
        }
 
        internal void AppendAttributeSkipNotify(XAttribute a) {
            a.parent = this;
            if (lastAttr == null) {
                a.next = a; 
            }
            else { 
                a.next = lastAttr.next; 
                lastAttr.next = a;
            } 
            lastAttr = a;
        }

        bool AttributesEqual(XElement e) { 
            XAttribute a1 = lastAttr;
            XAttribute a2 = e.lastAttr; 
            if (a1 != null && a2 != null) { 
                do {
                    a1 = a1.next; 
                    a2 = a2.next;
                    if (a1.name != a2.name || a1.value != a2.value) return false;
                } while (a1 != lastAttr);
                return a2 == e.lastAttr; 
            }
            return a1 == null && a2 == null; 
        } 

        internal override XNode CloneNode() { 
            return new XElement(this);
        }

        internal override bool DeepEquals(XNode node) { 
            XElement e = node as XElement;
            return e != null && name == e.name && ContentsEqual(e) && AttributesEqual(e); 
        } 

        IEnumerable GetAttributes(XName name) { 
            XAttribute a = lastAttr;
            if (a != null) {
                do {
                    a = a.next; 
                    if (name == null || a.name == name) yield return a;
                } while (a.parent == this && a != lastAttr); 
            } 
        }
 
        string GetNamespaceOfPrefixInScope(string prefix, XElement outOfScope) {
            XElement e = this;
            while (e != outOfScope) {
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do { 
                        a = a.next; 
                        if (a.IsNamespaceDeclaration && a.Name.LocalName == prefix) return a.Value;
                    } 
                    while (a != e.lastAttr);
                }
                e = e.parent as XElement;
            } 
            return null;
        } 
 
        internal override int GetDeepHashCode() {
            int h = name.GetHashCode(); 
            h ^= ContentsHashCode();
            XAttribute a = lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    h ^= a.GetDeepHashCode(); 
                } while (a != lastAttr); 
            }
            return h; 
        }

        void ReadElementFrom(XmlReader r, LoadOptions o) {
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive)); 
            name = XNamespace.Get(r.NamespaceURI).GetName(r.LocalName);
            if ((o & LoadOptions.SetBaseUri) != 0) { 
                string baseUri = r.BaseURI; 
                if (baseUri != null && baseUri.Length != 0) {
                    SetBaseUri(baseUri); 
                }
            }
            IXmlLineInfo li = null;
            if ((o & LoadOptions.SetLineInfo) != 0) { 
                li = r as IXmlLineInfo;
                if (li != null && li.HasLineInfo()) { 
                    SetLineInfo(li.LineNumber, li.LinePosition); 
                }
            } 
            if (r.MoveToFirstAttribute()) {
                do {
                    XAttribute a = new XAttribute(XNamespace.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
                    if (li != null && li.HasLineInfo()) { 
                        a.SetLineInfo(li.LineNumber, li.LinePosition);
                    } 
                    AppendAttributeSkipNotify(a); 
                } while (r.MoveToNextAttribute());
                r.MoveToElement(); 
            }
            if (!r.IsEmptyElement) {
                r.Read();
                ReadContentFrom(r, o); 
            }
            r.Read(); 
        } 

        internal void RemoveAttribute(XAttribute a) { 
            bool notify = NotifyChanging(a, XObjectChangeEventArgs.Remove);
            if (a.parent != this) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            XAttribute p = lastAttr, n;
            while ((n = p.next) != a) p = n; 
            if (p == a) {
                lastAttr = null; 
            } 
            else {
                if (lastAttr == a) lastAttr = p; 
                p.next = a.next;
            }
            a.parent = null;
            a.next = null; 
            if (notify) NotifyChanged(a, XObjectChangeEventArgs.Remove);
        } 
 
        void RemoveAttributesSkipNotify() {
            if (lastAttr != null) { 
                XAttribute a = lastAttr;
                do {
                    XAttribute next = a.next;
                    a.parent = null; 
                    a.next = null;
                    a = next; 
                } while (a != lastAttr); 
                lastAttr = null;
            } 
        }

        internal override void ValidateNode(XNode node, XNode previous) {
            if (node is XDocument) throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.Document)); 
            if (node is XDocumentType) throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.DocumentType));
        } 
    } 

    internal struct ElementWriter 
    {
        XmlWriter writer;
        NamespaceResolver resolver;
 
        public ElementWriter(XmlWriter writer) {
            this.writer = writer; 
            this.resolver = new NamespaceResolver(); 
        }
 
        public void WriteElement(XElement e) {
            PushAncestors(e);
            XElement root = e;
            XNode n = e; 
            while (true) {
                e = n as XElement; 
                if (e != null) { 
                    WriteStartElement(e);
                    if (e.content == null) { 
                        WriteEndElement();
                    }
                    else {
                        string s = e.content as string; 
                        if (s != null) {
                            writer.WriteString(s); 
                            WriteFullEndElement(); 
                        }
                        else { 
                            n = ((XNode)e.content).next;
                            continue;
                        }
                    } 
                }
                else { 
                    n.WriteTo(writer); 
                }
                while (n != root && n == n.parent.content) { 
                    n = n.parent;
                    WriteFullEndElement();

                } 
                if (n == root) break;
                n = n.next; 
            } 
        }
 
        string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) {
            string namespaceName = ns.NamespaceName;
            if (namespaceName.Length == 0) return string.Empty;
            string prefix = resolver.GetPrefixOfNamespace(ns, allowDefaultNamespace); 
            if (prefix != null) return prefix;
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml"; 
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns"; 
            return null;
        } 

        void PushAncestors(XElement e) {
            while (true) {
                e = e.parent as XElement; 
                if (e == null) break;
                XAttribute a = e.lastAttr; 
                if (a != null) { 
                    do {
                        a = a.next; 
                        if (a.IsNamespaceDeclaration) {
                            resolver.AddFirst(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value));
                        }
                    } while (a != e.lastAttr); 
                }
            } 
        } 

        void PushElement(XElement e) { 
            resolver.PushScope();
            XAttribute a = e.lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    if (a.IsNamespaceDeclaration) { 
                        resolver.Add(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value)); 
                    }
                } while (a != e.lastAttr); 
            }
        }

        void WriteEndElement() { 
            writer.WriteEndElement();
            resolver.PopScope(); 
        } 

        void WriteFullEndElement() { 
            writer.WriteFullEndElement();
            resolver.PopScope();
        }
 
        void WriteStartElement(XElement e) {
            PushElement(e); 
            XNamespace ns = e.Name.Namespace; 
            writer.WriteStartElement(GetPrefixOfNamespace(ns, true), e.Name.LocalName, ns.NamespaceName);
            XAttribute a = e.lastAttr; 
            if (a != null) {
                do {
                    a = a.next;
                    ns = a.Name.Namespace; 
                    string localName = a.Name.LocalName;
                    string namespaceName = ns.NamespaceName; 
                    writer.WriteAttributeString(GetPrefixOfNamespace(ns, false), localName, namespaceName.Length == 0 && localName == "xmlns" ? XNamespace.xmlnsPrefixNamespace : namespaceName, a.Value); 
                } while (a != e.lastAttr);
            } 
        }
    }

    internal struct NamespaceResolver { 
        class NamespaceDeclaration {
            public string prefix; 
            public XNamespace ns; 
            public int scope;
            public NamespaceDeclaration prev; 
        }

        int scope;
        NamespaceDeclaration declaration; 
        NamespaceDeclaration rover;
 
        public void PushScope() { 
            scope++;
        } 

        public void PopScope() {
            NamespaceDeclaration d = declaration;
            if (d != null) { 
                do {
                    d = d.prev; 
                    if (d.scope != scope) break; 
                    if (d == declaration) {
                        declaration = null; 
                    }
                    else {
                        declaration.prev = d.prev;
                    } 
                    rover = null;
                } while (d != declaration && declaration != null); 
            } 
            scope--;
        } 

        public void Add(string prefix, XNamespace ns) {
            NamespaceDeclaration d = new NamespaceDeclaration();
            d.prefix = prefix; 
            d.ns = ns;
            d.scope = scope; 
            if (declaration == null) { 
                declaration = d;
            } 
            else {
                d.prev = declaration.prev;
            }
            declaration.prev = d; 
            rover = null;
        } 
 
        public void AddFirst(string prefix, XNamespace ns) {
            NamespaceDeclaration d = new NamespaceDeclaration(); 
            d.prefix = prefix;
            d.ns = ns;
            d.scope = scope;
            if (declaration == null) { 
                d.prev = d;
            } 
            else { 
                d.prev = declaration.prev;
                declaration.prev = d; 
            }
            declaration = d;
            rover = null;
        } 

        // Only elements allow default namespace declarations. The rover 
        // caches the last namespace declaration used by an element. 
        public string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) {
            if (rover != null && rover.ns == ns && (allowDefaultNamespace || rover.prefix.Length > 0)) return rover.prefix; 
            NamespaceDeclaration d = declaration;
            if (d != null) {
                do {
                    d = d.prev; 
                    if (d.ns == ns) {
                        NamespaceDeclaration x = declaration.prev; 
                        while (x != d && x.prefix != d.prefix) { 
                            x = x.prev;
                        } 
                        if (x == d) {
                            if (allowDefaultNamespace) {
                                rover = d;
                                return d.prefix; 
                            }
                            else if (d.prefix.Length > 0) { 
                                return d.prefix; 
                            }
                        } 
                    }
                } while (d != declaration);
            }
            return null; 
        }
    } 
 
    /// 
    /// Specifies a set of options for Load(). 
    /// 
    [Flags()]
    public enum LoadOptions {
        /// Default options. 
        None                = 0x00000000,
 
        /// Preserve whitespace. 
        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification="Back-compat with System.Xml.")]
        PreserveWhitespace  = 0x00000001, 

        /// Set the BaseUri property.
        SetBaseUri          = 0x00000002,
 
        /// Set the IXmlLineInfo.
        SetLineInfo         = 0x00000004, 
    } 

    ///  
    /// Specifies a set of options for Save().
    /// 
    [Flags()]
    public enum SaveOptions { 
        /// Default options.
        None                = 0x00000000, 
 
        /// Disable formatting.
        DisableFormatting   = 0x00000001, 
    }

    /// 
    /// Represents an XML document. 
    /// 
    ///  
    /// An  can contain: 
    /// 
    ///    
    ///   A Document Type Declaration (DTD), see 
    ///   
    ///   One root element.
    ///   Zero or more  objects. 
    ///   Zero or more  objects.
    ///  
    ///  
    public class XDocument : XContainer
    { 
        XDeclaration declaration;

        ///
        /// Initializes a new instance of the  class. 
        /// Overloaded constructors are provided for creating a new empty
        /// , creating an  with 
        /// a parameter list of initial content, and as a copy of another 
        ///  object.
        ///  
        /// 
        /// Initializes a new instance of the  class.
        /// 
        public XDocument() { 
        }
 
        ///  
        /// Initializes a new instance of the  class with the specified content.
        ///  
        /// 
        /// A parameter list of content objects to add to this document.
        /// 
        ///  
        /// Valid content includes:
        ///  
        /// Zero or one  objects 
        /// Zero or one elements
        /// Zero or more comments 
        /// Zero or more processing instructions
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public XDocument(params object[] content) : this() { 
            AddContentSkipNotify(content); 
        }
 
        /// 
        /// Initializes a new instance of the  class
        /// with the specifed  and content.
        ///  
        /// 
        /// The XML declaration for the document. 
        ///  
        /// 
        /// The contents of the document. 
        /// 
        /// 
        /// Valid content includes:
        ///  
        /// Zero or one  objects
        /// Zero or one elements 
        /// Zero or more comments 
        /// Zero or more processing instructions
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method.
        ///  
        public XDocument(XDeclaration declaration, params object[] content) : this(content) {
            this.declaration = declaration; 
        } 

        ///  
        /// Initializes a new instance of the  class from an
        /// existing XDocument object.
        /// 
        ///  
        /// The  object that will be copied.
        ///  
        public XDocument(XDocument other) : base(other) { 
            if (other.declaration != null) {
                declaration = new XDeclaration(other.declaration); 
            }
        }

        ///  
        /// Gets the XML declaration for this document.
        ///  
        public XDeclaration Declaration { 
            get { return declaration; }
            set { declaration = value; } 
        }

        /// 
        /// Gets the Document Type Definition (DTD) for this document. 
        /// 
        public XDocumentType DocumentType { 
            get { 
                return GetFirstNode();
            } 
        }

        /// 
        /// Gets the node type for this node. 
        /// 
        ///  
        /// This property will always return XmlNodeType.Document. 
        /// 
        public override XmlNodeType NodeType { 
            get {
                return XmlNodeType.Document;
            }
        } 

        ///  
        /// Gets the root element of the XML Tree for this document. 
        /// 
        public XElement Root { 
            get {
                return GetFirstNode();
            }
        } 

        ///  
        /// The Load method provides multiple strategies for creating a new 
        ///  and initializing it from a data source containing
        /// raw XML.  Load from a file (passing in a URI to the file), an 
        /// , a , or an
        /// .  Note:  Use 
        /// to create an  from a string containing XML.
        ///  
        /// 
        ///  
        /// Create a new  based on the contents of the file 
        /// referenced by the URI parameter passed in.  Note: Use
        ///  to create an  from 
        /// a string containing XML.
        /// 
        /// 
        ///  
        /// 
        /// This method uses the  constructor to create 
        /// an  to read the raw XML into the underlying 
        /// XML tree.
        ///  
        /// 
        /// A URI string referencing the file to load into a new .
        /// 
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed in uri parameter. 
        ///  
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId="0#", Justification = "Back-compat with System.Xml.")]
        public static XDocument Load(string uri) { 
            return Load(uri, LoadOptions.None);
        }

        ///  
        /// Create a new  based on the contents of the file
        /// referenced by the URI parameter passed in.  Optionally, whitespace can be preserved. 
        ///  
        /// 
        ///  
        /// This method uses the  constructor to create
        /// an  to read the raw XML into an underlying
        /// XML tree.  If LoadOptions.PreserveWhitespace is enabled then
        /// the  property  
        /// is set to .
        ///  
        ///  
        /// A string representing the URI of the file to be loaded into a new .
        ///  
        /// 
        /// A set of .
        /// 
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed uri parameter.  If LoadOptions.PreserveWhitespace is enabled then 
        /// significant whitespace will be preserved. 
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId="0#", Justification = "Back-compat with System.Xml.")] 
        public static XDocument Load(string uri, LoadOptions options) {
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(uri, rs)) {
                return Load(r, options); 
            }
        } 
 
        /// 
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.
        /// 
        /// 
        /// A  containing the raw XML to read into the newly 
        /// created .
        ///  
        ///  
        /// A new  containing the contents of the passed in
        /// . 
        /// 
        public static XDocument Load(TextReader textReader) {
            return Load(textReader, LoadOptions.None);
        } 

        ///  
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.  Optionally whitespace handling
        /// can be preserved. 
        /// 
        /// 
        /// If LoadOptions.PreserveWhitespace is enabled then
        /// the  property  
        /// is set to .
        ///  
        ///  
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        /// 
        /// A set of .
        ///  
        /// 
        /// A new  containing the contents of the passed in 
        /// . 
        /// 
        public static XDocument Load(TextReader textReader, LoadOptions options) { 
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(textReader, rs)) {
                return Load(r, options);
            } 
        }
 
        ///  
        /// Create a new  containing the contents of the
        /// passed in . 
        /// 
        /// 
        /// An  containing the XML to be read into the new
        /// . 
        /// 
        ///  
        /// A new  containing the contents of the passed 
        /// in .
        ///  
        public static XDocument Load(XmlReader reader) {
            return Load(reader, LoadOptions.None);
        }
 
        /// 
        /// Create a new  containing the contents of the 
        /// passed in . 
        /// 
        ///  
        /// An  containing the XML to be read into the new
        /// .
        /// 
        ///  
        /// A set of .
        ///  
        ///  
        /// A new  containing the contents of the passed
        /// in . 
        /// 
        public static XDocument Load(XmlReader reader, LoadOptions options) {
            if (reader == null) throw new ArgumentNullException("reader");
            if (reader.ReadState == ReadState.Initial) reader.Read(); 
            XDocument d = new XDocument();
            if ((options & LoadOptions.SetBaseUri) != 0) { 
                string baseUri = reader.BaseURI; 
                if (baseUri != null && baseUri.Length != 0) {
                    d.SetBaseUri(baseUri); 
                }
            }
            if ((options & LoadOptions.SetLineInfo) != 0) {
                IXmlLineInfo li = reader as IXmlLineInfo; 
                if (li != null && li.HasLineInfo()) {
                    d.SetLineInfo(li.LineNumber, li.LinePosition); 
                } 
            }
            if (reader.NodeType == XmlNodeType.XmlDeclaration) { 
                d.Declaration = new XDeclaration(reader);
            }
            d.ReadContentFrom(reader, options);
            if (!reader.EOF) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedEndOfFile)); 
            if (d.Root == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingRoot));
            return d; 
        } 

        ///  
        /// Create a new  from a string containing
        /// XML.  Optionally whitespace can be preserved.
        /// 
        ///  
        /// Create a new  from a string containing
        /// XML. 
        ///  
        /// 
        /// A string containing XML. 
        /// 
        /// 
        /// An  containing an XML tree initialized from the
        /// passed in XML string. 
        /// 
        public static XDocument Parse(string text) { 
            return Parse(text, LoadOptions.None); 
        }
 
        /// 
        /// Create a new  from a string containing
        /// XML.  Optionally whitespace can be preserved.
        ///  
        /// 
        /// This method uses  passing it a StringReader 
        /// constructed from the passed in XML String.  If LoadOptions.PreserveWhitespace 
        /// is enabled then  is
        /// set to .  See  
        /// for more information on whitespace handling.
        /// 
        /// 
        /// A string containing XML. 
        /// 
        ///  
        /// A set of . 
        /// 
        ///  
        /// An  containing an XML tree initialized from the
        /// passed in XML string.
        /// 
        public static XDocument Parse(string text, LoadOptions options) { 
            using (StringReader sr = new StringReader(text)) {
                XmlReaderSettings rs = GetXmlReaderSettings(options); 
                using (XmlReader r = XmlReader.Create(sr, rs)) { 
                    return Load(r, options);
                } 
            }
        }

        /// 
        /// Outputs this 's underlying XML tree.  The output can
        /// be saved to a file, an , a , 
        /// or an .  Optionally whitespace can be preserved. 
        /// 
        ///  
        /// Output this  to a file.
        /// 
        /// 
        /// The format will be indented by default.  If you want 
        /// no indenting then use the SaveOptions version of Save (see
        /// ) enabling 
        /// SaveOptions.DisableFormatting. 
        /// 
        ///  
        /// The name of the file to output the XML to.
        /// 
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None); 
        }
 
        ///  
        /// Output this  to a file.
        ///  
        /// 
        /// The name of the file to output the XML to.
        /// 
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            if (declaration != null && !string.IsNullOrEmpty(declaration.Encoding)) { 
                try {
                    ws.Encoding = Encoding.GetEncoding(declaration.Encoding);
                }
                catch (ArgumentException) { 
                }
            } 
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) { 
                Save(w);
            } 
        }

        /// 
        /// Output this  to the passed in . 
        /// 
        ///  
        /// The format will be indented by default.  If you want 
        /// no indenting then use the SaveOptions version of Save (see
        /// ) enabling 
        /// SaveOptions.DisableFormatting
        /// 
        /// 
        /// The  to output this  to. 
        /// 
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None); 
        }
 
        /// 
        /// Output this  to a .
        /// 
        ///  
        /// The  to output the XML to.
        ///  
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) {
                Save(w); 
            }
        } 
 
        /// 
        /// Output this  to an . 
        /// 
        /// 
        /// The  to output the XML to.
        ///  
        public void Save(XmlWriter writer) {
            WriteTo(writer); 
        } 

 
        /// 
        /// Output this 's underlying XML tree to the
        /// passed in .
        ///  
        /// 
        ///  
        /// The  to output the content of this 
        /// .
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            if (declaration != null && declaration.Standalone == "yes") {
                writer.WriteStartDocument(true); 
            }
            else if (declaration != null && declaration.Standalone == "no") { 
                writer.WriteStartDocument(false); 
            }
            else { 
                writer.WriteStartDocument();
            }
            WriteContentTo(writer);
            writer.WriteEndDocument(); 
        }
 
        internal override void  AddAttribute(XAttribute a) { 
            throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
        } 

        internal override void  AddAttributeSkipNotify(XAttribute a) {
            throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
        } 

        internal override XNode CloneNode() { 
            return new XDocument(this); 
        }
 
        internal override bool DeepEquals(XNode node) {
            XDocument other = node as XDocument;
            return other != null && ContentsEqual(other);
        } 

        internal override int GetDeepHashCode() { 
            return ContentsHashCode(); 
        }
 
        T GetFirstNode() where T : XNode {
            XNode n = content as XNode;
            if (n != null) {
                do { 
                    n = n.next;
                    T e = n as T; 
                    if (e != null) return e; 
                } while (n != content);
            } 
            return null;
        }

        internal static bool IsWhitespace(string s) { 
            foreach (char ch in s) {
                if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') return false; 
            } 
            return true;
        } 

        internal override void ValidateNode(XNode node, XNode previous) {
            switch (node.NodeType) {
                case XmlNodeType.Text: 
                    ValidateString(((XText)node).Value);
                    break; 
                case XmlNodeType.Element: 
                    ValidateDocument(previous, XmlNodeType.DocumentType, XmlNodeType.None);
                    break; 
                case XmlNodeType.DocumentType:
                    ValidateDocument(previous, XmlNodeType.None, XmlNodeType.Element);
                    break;
                case XmlNodeType.CDATA: 
                    throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.CDATA));
                case XmlNodeType.Document: 
                    throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.Document)); 
            }
        } 

        void ValidateDocument(XNode previous, XmlNodeType allowBefore, XmlNodeType allowAfter) {
            XNode n = content as XNode;
            if (n != null) { 
                if (previous == null) allowBefore = allowAfter;
                do { 
                    n = n.next; 
                    XmlNodeType nt = n.NodeType;
                    if (nt == XmlNodeType.Element || nt == XmlNodeType.DocumentType) { 
                        if (nt != allowBefore) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DocumentStructure));
                        allowBefore = XmlNodeType.None;
                    }
                    if (n == previous) allowBefore = allowAfter; 
                } while (n != content);
            } 
        } 

        internal override void ValidateString(string s) { 
            if (!IsWhitespace(s)) throw new ArgumentException(Res.GetString(Res.Argument_AddNonWhitespace));
        }
    }
 
    /// 
    /// Represents an XML comment. 
    ///  
    public class XComment : XNode
    { 
        internal string value;

        /// 
        /// Initializes a new instance of the  class. 
        /// 
        ///  
        /// Initializes a new instance of the  class with the 
        /// specified string content.
        ///  
        /// 
        /// The contents of the new XComment object.
        /// 
        ///  
        /// Thrown if the specified value is null.
        ///  
        public XComment(string value) { 
            if (value == null) throw new ArgumentNullException("value");
            this.value = value; 
        }

        /// 
        /// Initializes a new comment node from an existing comment node. 
        /// 
        /// Comment node to copy from. 
        public XComment(XComment other) { 
            if (other == null) throw new ArgumentNullException("other");
            this.value = other.value; 
        }

        internal XComment(XmlReader r) {
            value = r.Value; 
            r.Read();
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.Comment.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.Comment; 
            }
        } 

        /// 
        /// Gets or sets the string value of this comment.
        ///  
        /// 
        /// Thrown if the specified value is null. 
        ///  
        public string Value {
            get { 
                return value;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                this.value = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 

        /// 
        /// Write this  to the passed in .
        ///  
        /// 
        /// The  to write this  to. 
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteComment(value);
        }

        internal override XNode CloneNode() { 
            return new XComment(this);
        } 
 
        internal override bool DeepEquals(XNode node) {
            XComment other = node as XComment; 
            return other != null && value == other.value;
        }

        internal override int GetDeepHashCode() { 
            return value.GetHashCode();
        } 
    } 

    ///  
    /// Represents an XML processing instruction.
    /// 
    public class XProcessingInstruction : XNode
    { 
        internal string target;
        internal string data; 
 
        /// 
        /// Initializes a new XML Processing Instruction from the specified target and string data. 
        /// 
        /// 
        /// The target application for this .
        ///  
        /// 
        /// The string data that comprises the . 
        ///  
        /// 
        /// Thrown if either the target or data parameter are null. 
        /// 
        public XProcessingInstruction(string target, string data) {
            if (data == null) throw new ArgumentNullException("data");
            ValidateName(target); 
            this.target = target;
            this.data = data; 
        } 

        ///  
        /// Initializes a new XML processing instruction by copying its target and data
        /// from another XML processing instruction.
        /// 
        /// XML processing instruction to copy from. 
        public XProcessingInstruction(XProcessingInstruction other) {
            if (other == null) throw new ArgumentNullException("other"); 
            this.target = other.target; 
            this.data = other.data;
        } 

        internal XProcessingInstruction(XmlReader r) {
            target = r.Name;
            data = r.Value; 
            r.Read();
        } 
 
        /// 
        /// Gets or sets the string value of this processing instruction. 
        /// 
        /// 
        /// Thrown if the value set is null.
        ///  
        public string Data {
            get { 
                return data; 
            }
            set { 
                if (value == null) throw new ArgumentNullException("value");
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                data = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.ProcessingInstruction.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.ProcessingInstruction; 
            }
        } 

        /// 
        /// Gets or sets a string representing the target application for this processing instruction.
        ///  
        /// 
        /// Thrown if the value set is null. 
        ///  
        public string Target {
            get { 
                return target;
            }
            set {
                ValidateName(value); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                target = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name); 
            }
        } 

        /// 
        /// Writes this  to the passed in .
        ///  
        /// 
        /// The  to write this  to. 
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteProcessingInstruction(target, data);
        }

        internal override XNode CloneNode() { 
            return new XProcessingInstruction(this);
        } 
 
        internal override bool DeepEquals(XNode node) {
            XProcessingInstruction other = node as XProcessingInstruction; 
            return other != null && target == other.target && data == other.data;
        }

        internal override int GetDeepHashCode() { 
            return target.GetHashCode() ^ data.GetHashCode();
        } 
 
        static void ValidateName(string name) {
            XmlConvert.VerifyNCName(name); 
            if (string.Compare(name, "xml", StringComparison.OrdinalIgnoreCase) == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidPIName, name));
        }
    }
 
    /// 
    /// Represents an XML declaration. 
    ///  
    /// 
    /// An XML declaration is used to declare the XML version, 
    /// the encoding, and whether or not the XML document is standalone.
    /// 
    public class XDeclaration
    { 
        string version;
        string encoding; 
        string standalone; 

        ///  
        /// Initilizes a new instance of the  class from the
        /// specified version, encoding, and standalone properties.
        /// 
        ///  
        /// The version of the XML, usually "1.0".
        ///  
        ///  
        /// The encoding for the XML document.
        ///  
        /// 
        /// Specifies whether the XML is standalone or requires external entities
        /// to be resolved.
        ///  
        public XDeclaration(string version, string encoding, string standalone) {
            this.version = version; 
            this.encoding = encoding; 
            this.standalone = standalone;
        } 

        /// 
        /// Initializes an instance of the  class
        /// from another  object. 
        /// 
        ///  
        /// The  used to initialize this  object. 
        /// 
        public XDeclaration(XDeclaration other) { 
            if (other == null) throw new ArgumentNullException("other");
            version = other.version;
            encoding = other.encoding;
            standalone = other.standalone; 
        }
 
        internal XDeclaration(XmlReader r) { 
            version = r.GetAttribute("version");
            encoding = r.GetAttribute("encoding"); 
            standalone = r.GetAttribute("standalone");
            r.Read();
        }
 
        /// 
        /// Gets or sets the encoding for this document. 
        ///  
        public string Encoding {
            get { return encoding; } 
            set { encoding = value; }
        }

        ///  
        /// Gets or sets the standalone property for this document.
        ///  
        ///  
        /// The valid values for standalone are "yes" or "no".
        ///  
        public string Standalone {
            get { return standalone; }
            set { standalone = value; }
        } 

        ///  
        /// Gets or sets the version property for this document. 
        /// 
        ///  
        /// The value is usually "1.0".
        /// 
        public string Version {
            get { return version; } 
            set { version = value; }
        } 
 
        /// 
        /// Provides a formatted string. 
        /// 
        /// A formatted XML string.
        public override string ToString() {
            StringBuilder sb = new StringBuilder("");
            return sb.ToString();
        } 
    }
 
    ///  
    /// Represents an XML Document Type Definition (DTD).
    ///  
    public class XDocumentType : XNode
    {
        string name;
        string publicId; 
        string systemId;
        string internalSubset; 
 
        /// 
        /// Initializes an empty instance of the  class. 
        /// 
        public XDocumentType(string name, string publicId, string systemId, string internalSubset) {
            this.name = XmlConvert.VerifyName(name);
            this.publicId = publicId; 
            this.systemId = systemId;
            this.internalSubset = internalSubset; 
        } 

        ///  
        /// Initializes an instance of the XDocumentType class
        /// from another XDocumentType object.
        /// 
        ///  object to copy from. 
        public XDocumentType(XDocumentType other) {
            if (other == null) throw new ArgumentNullException("other"); 
            this.name = other.name; 
            this.publicId = other.publicId;
            this.systemId = other.systemId; 
            this.internalSubset = other.internalSubset;
        }

        internal XDocumentType(XmlReader r) { 
            name = r.Name;
            publicId = r.GetAttribute("PUBLIC"); 
            systemId = r.GetAttribute("SYSTEM"); 
            internalSubset = r.Value;
            r.Read(); 
        }

        /// 
        /// Gets or sets the internal subset for this Document Type Definition (DTD). 
        /// 
        public string InternalSubset { 
            get { 
                return internalSubset;
            } 
            set {
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                internalSubset = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 
 
        /// 
        /// Gets or sets the name for this Document Type Definition (DTD). 
        /// 
        public string Name {
            get {
                return name; 
            }
            set { 
                value = XmlConvert.VerifyName(value); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                name = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name);
            }
        }
 
        /// 
        /// Gets the node type for this node. 
        ///  
        /// 
        /// This property will always return XmlNodeType.DocumentType. 
        /// 
        public override XmlNodeType NodeType {
            get {
                return XmlNodeType.DocumentType; 
            }
        } 
 
        /// 
        /// Gets or sets the public identifier for this Document Type Definition (DTD). 
        /// 
        public string PublicId {
            get {
                return publicId; 
            }
            set { 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                publicId = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        }

        ///  
        /// Gets or sets the system identifier for this Document Type Definition (DTD).
        ///  
        public string SystemId { 
            get {
                return systemId; 
            }
            set {
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                systemId = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value);
            } 
        } 

        ///  
        /// Write this  to the passed in .
        /// 
        /// 
        /// The  to write this  to. 
        /// 
        public override void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteDocType(name, publicId, systemId, internalSubset);
        } 

        internal override XNode CloneNode() {
            return new XDocumentType(this);
        } 

        internal override bool DeepEquals(XNode node) { 
            XDocumentType other = node as XDocumentType; 
            return other != null && name == other.name && publicId == other.publicId &&
                systemId == other.SystemId && internalSubset == other.internalSubset; 
        }

        internal override int GetDeepHashCode() {
            return name.GetHashCode() ^ 
                (publicId != null ? publicId.GetHashCode() : 0) ^
                (systemId != null ? systemId.GetHashCode() : 0) ^ 
                (internalSubset != null ? internalSubset.GetHashCode() : 0); 
        }
    } 

    /// 
    /// Represents an XML attribute.
    ///  
    /// 
    /// An XML attribute is a name/value pair associated with an XML element. 
    ///  
    [System.ComponentModel.TypeDescriptionProvider(typeof(ComponentModel.XTypeDescriptionProvider))]
    [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "Reviewed.")] 
    public class XAttribute : XObject
    {
        static IEnumerable emptySequence;
 
        /// 
        /// Gets an empty collection of attributes. 
        ///  
        public static IEnumerable EmptySequence {
            get { 
                if (emptySequence == null) emptySequence = new XAttribute[0];
                return emptySequence;
            }
        } 

        internal XAttribute next; 
        internal XName name; 
        internal string value;
 
        /// 
        /// Initializes a new instance of the  class.
        /// 
        ///  
        /// Initializes a new instance of the  class from
        /// the specified name and value. 
        ///  
        /// 
        /// The name of the attribute. 
        /// 
        /// 
        /// The value of the attribute.
        ///  
        /// 
        /// Thrown if the passed in name or value are null. 
        ///  
        public XAttribute(XName name, object value) {
            if (name == null) throw new ArgumentNullException("name"); 
            if (value == null) throw new ArgumentNullException("value");
            string s = XContainer.GetStringValue(value);
            ValidateAttribute(name, s);
            this.name = name; 
            this.value = s;
        } 
 
        /// 
        /// Initializes an instance of the XAttribute class 
        /// from another XAttribute object.
        /// 
        ///  object to copy from.
        ///  
        /// Thrown if the specified  is null.
        ///  
        public XAttribute(XAttribute other) { 
            if (other == null) throw new ArgumentNullException("other");
            name = other.name; 
            value = other.value;
        }

        ///  
        /// Gets a value indicating if this attribute is a namespace declaration.
        ///  
        public bool IsNamespaceDeclaration { 
            get {
                string namespaceName = name.NamespaceName; 
                if (namespaceName.Length == 0) {
                    return name.LocalName == "xmlns";
                }
                return (object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace; 
            }
        } 
 
        /// 
        /// Gets the name of this attribute. 
        /// 
        public XName Name {
            get { return name; }
        } 

        ///  
        /// Gets the next attribute of the parent element. 
        /// 
        ///  
        /// If this attribute does not have a parent, or if there is no next attribute,
        /// then this property returns null.
        /// 
        public XAttribute NextAttribute { 
            get { return parent != null && ((XElement)parent).lastAttr != this ? next : null; }
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.Attribute.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.Attribute; 
            }
        } 

        /// 
        /// Gets the previous attribute of the parent element.
        ///  
        /// 
        /// If this attribute does not have a parent, or if there is no previous attribute, 
        /// then this property returns null. 
        /// 
        public XAttribute PreviousAttribute { 
            get {
                if (parent == null) return null;
                XAttribute a = ((XElement)parent).lastAttr;
                while (a.next != this) { 
                    a = a.next;
                } 
                return a != ((XElement)parent).lastAttr ? a : null; 
            }
        } 

        /// 
        /// Gets or sets the value of this attribute.
        ///  
        /// 
        /// Thrown if the value set is null. 
        ///  
        public string Value {
            get { 
                return value;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                ValidateAttribute(name, value);
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                this.value = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value);
            } 
        }

        /// 
        /// Deletes this XAttribute. 
        /// 
        ///  
        /// Thrown if the parent element is null. 
        /// 
        public void Remove() { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            ((XElement)parent).RemoveAttribute(this);
        }
 
        /// 
        /// Sets the value of this . 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// The value to assign to this attribute. The value is converted to its string
        /// representation and assigned to the  property. 
        /// 
        ///  
        /// Thrown if the specified value is null. 
        /// 
        public void SetValue(object value) { 
            if (value == null) throw new ArgumentNullException("value");
            Value = XContainer.GetStringValue(value);
        }
 
        /// 
        /// Override for  on  
        ///  
        /// XML text representation of an attribute and its value
        public override string ToString() { 
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) {
                XmlWriterSettings ws = new XmlWriterSettings();
                ws.ConformanceLevel = ConformanceLevel.Fragment;
                using (XmlWriter w = XmlWriter.Create(sw, ws)) { 
                    w.WriteAttributeString(GetPrefixOfNamespace(name.Namespace), name.LocalName, name.NamespaceName, value);
                } 
                return sw.ToString().Trim(); 
            }
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        [CLSCompliant(false)]
        public static explicit operator string(XAttribute attribute) {
            if (attribute == null) return null; 
            return attribute.value;
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator bool(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToBoolean(attribute.value.ToLower(CultureInfo.InvariantCulture));
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator bool?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToBoolean(attribute.value.ToLower(CultureInfo.InvariantCulture));
        }
 
        /// 
        /// Cast the value of this  to an . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as an .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator int(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToInt32(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as an ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator int?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToInt32(attribute.value);
        } 

        /// 
        /// Cast the value of this  to an .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as an . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator uint(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToUInt32(attribute.value);
        } 

        /// 
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as an ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator uint?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToUInt32(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator long(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToInt64(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator long?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToInt64(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to an . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as an .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator ulong(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToUInt64(attribute.value);
        }
 
         /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as an ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator ulong?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToUInt64(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator float(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToSingle(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator float?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToSingle(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator double(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToDouble(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator double?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToDouble(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator decimal(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToDecimal(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator decimal?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToDecimal(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator DateTime(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator DateTime?(XAttribute attribute) {
            if (attribute == null) return null; 
            return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator DateTimeOffset(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToDateTimeOffset(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator DateTimeOffset?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToDateTimeOffset(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator TimeSpan(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToTimeSpan(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator TimeSpan?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToTimeSpan(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator Guid(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToGuid(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator Guid?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToGuid(attribute.value);
        } 
 
        internal int GetDeepHashCode() {
            return name.GetHashCode() ^ value.GetHashCode(); 
        }

        internal string GetPrefixOfNamespace(XNamespace ns) {
            string namespaceName = ns.NamespaceName; 
            if (namespaceName.Length == 0) return string.Empty;
            if (parent != null) return ((XElement)parent).GetPrefixOfNamespace(ns); 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml"; 
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns";
            return null; 
        }

        static void ValidateAttribute(XName name, string value) {
            // The following constraints apply for namespace declarations: 
            string namespaceName = name.NamespaceName;
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) { 
                if (value.Length == 0) { 
                    // The empty namespace name can only be declared by
                    // the default namespace declaration 
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationPrefixed, name.LocalName));
                }
                else if (value == XNamespace.xmlPrefixNamespace) {
                    // 'http://www.w3.org/XML/1998/namespace' can only 
                    // be declared by the 'xml' prefix namespace declaration.
                    if (name.LocalName != "xml") throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml)); 
                } 
                else if (value == XNamespace.xmlnsPrefixNamespace) {
                    // 'http://www.w3.org/2000/xmlns/' must not be declared 
                    // by any namespace declaration.
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns));
                }
                else { 
                    string localName = name.LocalName;
                    if (localName == "xml") { 
                        // No other namespace name can be declared by the 'xml' 
                        // prefix namespace declaration.
                        throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml)); 
                    }
                    else if (localName == "xmlns") {
                        // The 'xmlns' prefix must not be declared.
                        throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns)); 
                    }
                } 
            } 
            else if (namespaceName.Length == 0 && name.LocalName == "xmlns") {
                if (value == XNamespace.xmlPrefixNamespace) { 
                    // 'http://www.w3.org/XML/1998/namespace' can only
                    // be declared by the 'xml' prefix namespace declaration.
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml));
                } 
                else if (value == XNamespace.xmlnsPrefixNamespace) {
                    // 'http://www.w3.org/2000/xmlns/' must not be declared 
                    // by any namespace declaration. 
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns));
                } 
            }
        }
    }
 
    /// 
    /// Represents a class that allows elements to be streamed 
    /// on input and output. 
    /// 
    public class XStreamingElement 
    {
        internal XName name;
        internal object content;
 
        /// 
        ///  Creates a  node with a given name 
        ///  
        /// The name to assign to the new  node
        public XStreamingElement(XName name) { 
            if (name == null) throw new ArgumentNullException("name");
            this.name = name;
        }
 
        /// 
        /// Creates a  node with a given name and content 
        ///  
        /// The name to assign to the new  node
        /// The content to assign to the new  node 
        public XStreamingElement(XName name, object content) : this(name) {
            this.content = content is List? new object[] { content } : content;
        }
 
        /// 
        /// Creates a  node with a given name and content 
        ///  
        /// The name to assign to the new  node
        /// An array containing content to assign to the new  node 
        public XStreamingElement(XName name, params object[] content) : this(name) {
            this.content = content;
        }
 
        /// 
        /// Gets or sets the name of this streaming element. 
        ///  
        public XName Name {
            get { 
                return name;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                name = value;
            } 
        } 

        ///  
        /// Add content to an 
        /// 
        /// Object containg content to add
        public void Add(object content) { 
            if (content != null) {
                List list = this.content as List; 
                if (list == null) { 
                    list = new List();
                    if (this.content != null) list.Add(this.content); 
                    this.content = list;
                }
                list.Add(content);
            } 
        }
 
        ///  
        /// Add content to an 
        ///  
        /// array of objects containg content to add
        public void Add(params object[] content) {
            Add((object)content);
        } 

 
        ///  
        /// Save an  to a file with formatting.
        ///  
        /// Name of file to write content to
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None);
        } 

        ///  
        /// Save an  to a file, optionally formatting. 
        /// 
        /// Name of file to write content to 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        /// 
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = XNode.GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) { 
                Save(w); 
            }
        } 

        /// 
        /// Save the contents of an  to a text writer
        /// with formatting. 
        /// 
        ///  to write to  
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None);
        } 

        /// 
        /// Save the contents of an  to a text writer
        /// optionally formatting. 
        /// 
        ///  to write to  
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = XNode.GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) {
                Save(w); 
            }
        } 
 
        /// 
        /// Save the contents of an  to an XML writer, not preserving whitepace 
        /// 
        ///  to write to 
        public void Save(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteStartDocument();
            WriteTo(writer); 
            writer.WriteEndDocument(); 
        }
 
        /// 
        /// Get the XML content of an  as a
        /// formatted string.
        ///  
        /// The XML text as a formatted string
        public override string ToString() { 
            return GetXmlString(SaveOptions.None); 
        }
 
        /// 
        /// Gets the XML content of this streaming element as a string.
        /// 
        /// If SaveOptions.DisableFormatting is enabled the 
        /// content is not indented.
        /// An XML string 
        public string ToString(SaveOptions options) { 
            return GetXmlString(options);
        } 

        /// 
        /// Write this  to an 
        ///  
        /// 
        public void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            new StreamingElementWriter(writer).WriteStreamingElement(this);
        } 

        string GetXmlString(SaveOptions o) {
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) {
                XmlWriterSettings ws = new XmlWriterSettings(); 
                ws.OmitXmlDeclaration = true;
                if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true; 
                using (XmlWriter w = XmlWriter.Create(sw, ws)) { 
                    WriteTo(w);
                } 
                return sw.ToString();
            }
        }
    } 

    internal struct StreamingElementWriter 
    { 
        XmlWriter writer;
        XStreamingElement element; 
        List attributes;
        NamespaceResolver resolver;

        public StreamingElementWriter(XmlWriter w) { 
            writer = w;
            element = null; 
            attributes = new List(); 
            resolver = new NamespaceResolver();
        } 

        void FlushElement() {
            if (element != null) {
                PushElement(); 
                XNamespace ns = element.Name.Namespace;
                writer.WriteStartElement(GetPrefixOfNamespace(ns, true), element.Name.LocalName, ns.NamespaceName); 
                foreach (XAttribute a in attributes) { 
                    ns = a.Name.Namespace;
                    string localName = a.Name.LocalName; 
                    string namespaceName = ns.NamespaceName;
                    writer.WriteAttributeString(GetPrefixOfNamespace(ns, false), localName, namespaceName.Length == 0 && localName == "xmlns" ? XNamespace.xmlnsPrefixNamespace : namespaceName, a.Value);
                }
                element = null; 
                attributes.Clear();
            } 
        } 

        string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) { 
            string namespaceName = ns.NamespaceName;
            if (namespaceName.Length == 0) return string.Empty;
            string prefix = resolver.GetPrefixOfNamespace(ns, allowDefaultNamespace);
            if (prefix != null) return prefix; 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml";
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns"; 
            return null; 
        }
 
        void PushElement() {
            resolver.PushScope();
            foreach (XAttribute a in attributes) {
                if (a.IsNamespaceDeclaration) { 
                    resolver.Add(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value));
                } 
            } 
        }
 
        void Write(object content) {
            if (content == null) return;
            XNode n = content as XNode;
            if (n != null) { 
                WriteNode(n);
                return; 
            } 
            string s = content as string;
            if (s != null) { 
                WriteString(s);
                return;
            }
            XAttribute a = content as XAttribute; 
            if (a != null) {
                WriteAttribute(a); 
                return; 
            }
            XStreamingElement x = content as XStreamingElement; 
            if (x != null) {
                WriteStreamingElement(x);
                return;
            } 
            object[] o = content as object[];
            if (o != null) { 
                foreach (object obj in o) Write(obj); 
                return;
            } 
            IEnumerable e = content as IEnumerable;
            if (e != null) {
                foreach (object obj in e) Write(obj);
                return; 
            }
            WriteString(XContainer.GetStringValue(content)); 
        } 

        void WriteAttribute(XAttribute a) { 
            if (element == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_WriteAttribute));
            attributes.Add(a);
        }
 
        void WriteNode(XNode n) {
            FlushElement(); 
            n.WriteTo(writer); 
        }
 
        internal void WriteStreamingElement(XStreamingElement e) {
            FlushElement();
            element = e;
            Write(e.content); 
            bool contentWritten = element == null;
            FlushElement(); 
            if (contentWritten) { 
                writer.WriteFullEndElement();
            } 
            else {
                writer.WriteEndElement();
            }
            resolver.PopScope(); 
        }
 
        void WriteString(string s) { 
            FlushElement();
            writer.WriteString(s); 
        }
    }

    ///  
    /// Defines the LINQ to XML extension methods.
    ///  
    public static class Extensions 
    {
        ///  
        /// Returns all of the s for each  of
        /// this  of .
        /// 
        ///  
        /// An  of  containing the XML
        /// Attributes for every  in the target  
        /// of . 
        /// 
        public static IEnumerable Attributes(this IEnumerable source) { 
            if (source == null) throw new ArgumentNullException("source");
            return GetAttributes(source, null);
        }
 
        /// 
        /// Returns the s that have a matching .  Each 
        /// 's s in the target  
        /// of  are scanned for a matching .
        ///  
        /// 
        /// An  of  containing the XML
        /// Attributes with a matching  for every  in
        /// the target  of . 
        /// 
        public static IEnumerable Attributes(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetAttributes(source, name) : XAttribute.EmptySequence;
        } 

        /// 
        /// Returns an  of  containing the ancestors (parent
        /// and it's parent up to the root) of each of the s in this 
        ///  of .
        ///  
        ///  
        /// An  of  containing the ancestors (parent
        /// and it's parent up to the root) of each of the s in this 
        ///  of .
        /// 
        public static IEnumerable Ancestors(this IEnumerable source) where T: XNode {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetAncestors(source, null, false);
        } 
 
        /// 
        /// Returns an  of  containing the ancestors (parent 
        /// and it's parent up to the root) that have a matching .  This is done for each
        ///  in this  of .
        /// 
        ///  
        /// An  of  containing the ancestors (parent
        /// and it's parent up to the root) that have a matching .  This is done for each 
        ///  in this  of . 
        /// 
        public static IEnumerable Ancestors(this IEnumerable source, XName name) where T: XNode { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetAncestors(source, name, false) : XElement.EmptySequence;
        }
 
        /// 
        /// Returns an  of  containing the 
        ///  and it's ancestors (parent and it's parent up to the root). 
        /// This is done for each  in this  of
        /// . 
        /// 
        /// 
        /// An  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root). 
        /// This is done for each  in this  of
        /// . 
        ///  
        public static IEnumerable AncestorsAndSelf(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetAncestors(source, null, true);
        }

        ///  
        /// Returns an  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root) 
        /// that match the passed in .  This is done for each 
        ///  in this  of .
        ///  
        /// 
        /// An  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root)
        /// that match the passed in .  This is done for each 
        ///  in this  of .
        ///  
        public static IEnumerable AncestorsAndSelf(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetAncestors(source, name, true) : XElement.EmptySequence; 
        }

        /// 
        /// Returns an  of  over the content of a set of nodes 
        /// 
        public static IEnumerable Nodes(this IEnumerable source) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source"); 
            foreach (XContainer root in source) {
                if (root != null) { 
                    XNode n = root.LastNode;
                    if (n != null) {
                        do {
                            n = n.next; 
                            yield return n;
                        } while (n.parent == root && n != root.content); 
                    } 
                }
            } 
        }

        /// 
        /// Returns an  of  over the descendants of a set of nodes 
        /// 
        public static IEnumerable DescendantNodes(this IEnumerable source) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendantNodes(source, false);
        } 

        /// 
        /// Returns an  of  containing the descendants (children
        /// and their children down to the leaf level).  This is done for each  in 
        /// this  of .
        ///  
        ///  
        /// An  of  containing the descendants (children
        /// and their children down to the leaf level).  This is done for each  in 
        /// this  of .
        /// 
        public static IEnumerable Descendants(this IEnumerable source) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendants(source, null, false);
        } 
 
        /// 
        /// Returns an  of  containing the descendants (children 
        /// and their children down to the leaf level) that have a matching .  This is done
        /// for each  in the target  of .
        /// 
        ///  
        /// An  of  containing the descendants (children
        /// and their children down to the leaf level) that have a matching .  This is done 
        /// for each  in this  of . 
        /// 
        public static IEnumerable Descendants(this IEnumerable source, XName name) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetDescendants(source, name, false) : XElement.EmptySequence;
        }
 
        /// 
        /// Returns an  of  containing the 
        ///  and it's descendants 
        /// that match the passed in .  This is done for each
        ///  in this  of . 
        /// 
        /// 
        /// An  of  containing the
        ///  and descendants. 
        /// This is done for each
        ///  in this  of . 
        ///  
        public static IEnumerable DescendantNodesAndSelf(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendantNodes(source, true);
        }

        ///  
        /// Returns an  of  containing the
        ///  and it's descendants (children and children's children down 
        /// to the leaf nodes).  This is done for each  in this  
        /// of .
        ///  
        /// 
        /// An  of  containing the
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes).  This is done for each  in this  
        /// of .
        ///  
        public static IEnumerable DescendantsAndSelf(this IEnumerable source) { 
            if (source == null) throw new ArgumentNullException("source");
            return GetDescendants(source, null, true); 
        }

        /// 
        /// Returns an  of  containing the 
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes) that match the passed in .  This is done for 
        /// each  in this  of . 
        /// 
        ///  
        /// An  of  containing the
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes) that match the passed in .  This is done for
        /// each  in this  of . 
        /// 
        public static IEnumerable DescendantsAndSelf(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetDescendants(source, name, true) : XElement.EmptySequence;
        } 

        /// 
        /// Returns an  of  containing the child elements
        /// for each  in this  of . 
        /// 
        ///  
        /// An  of  containing the child elements 
        /// for each  in this  of .
        ///  
        public static IEnumerable Elements(this IEnumerable source) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source");
            return GetElements(source, null);
        } 

        ///  
        /// Returns an  of  containing the child elements 
        /// with a matching for each  in this  of .
        ///  
        /// 
        /// An  of  containing the child elements
        /// for each  in this  of .
        ///  
        public static IEnumerable Elements(this IEnumerable source, XName name) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetElements(source, name) : XElement.EmptySequence; 
        }
 
        /// 
        /// Returns an  of  containing the child elements
        /// with a matching for each  in this  of .
        ///  
        /// 
        /// An  of  containing the child elements 
        /// for each  in this  of . 
        /// in document order
        ///  
        public static IEnumerable InDocumentOrder(this IEnumerable source) where T: XNode {
            return Enumerable.OrderBy(source, n => (XNode)n, XNode.DocumentOrderComparer);
        }
 
        /// 
        /// Removes each  represented in this  of 
        /// .  Note that this method uses snapshot semantics (copies the 
        /// attributes to a  before deleting each).
        ///  
        public static void Remove(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source");
            foreach (XAttribute a in new List(source))
                if (a != null) a.Remove(); 
        }
 
        ///  
        /// Removes each  represented in this 
        /// T which must be a derived from .  Note that this method uses snapshot semantics 
        /// (copies the s to a List before deleting each).
        /// 
        public static void Remove(this IEnumerable source) where T: XNode {
            if (source == null) throw new ArgumentNullException("source"); 
            foreach (T node in new List(source))
                if (node != null) node.Remove(); 
        } 

        static IEnumerable GetAttributes(IEnumerable source, XName name) { 
            foreach (XElement e in source) {
                if (e != null) {
                    XAttribute a = e.lastAttr;
                    if (a != null) { 
                        do {
                            a = a.next; 
                            if (name == null || a.name == name) yield return a; 
                        } while (a.parent == e && a != e.lastAttr);
                    } 
                }
            }
        }
 
        static IEnumerable GetAncestors(IEnumerable source, XName name, bool self) where T: XNode {
            foreach (XNode node in source) { 
                if (node != null) { 
                    XElement e = (self ? node : node.parent) as XElement;
                    while (e != null) { 
                        if (name == null || e.name == name) yield return e;
                        e = e.parent as XElement;
                    }
                } 
            }
        } 
 
        static IEnumerable GetDescendantNodes(IEnumerable source, bool self) where T: XContainer {
            foreach (XContainer root in source) { 
                if (root != null) {
                    if (self) yield return root;
                    XNode n = root;
                    while (true) { 
                        XContainer c = n as XContainer;
                        XNode first; 
                        if (c != null && (first = c.FirstNode) != null) { 
                            n = first;
                        } 
                        else {
                            while (n != null && n != root && n == n.parent.content) n = n.parent;
                            if (n == null || n == root) break;
                            n = n.next; 
                        }
                        yield return n; 
                    } 
                }
            } 
        }

        static IEnumerable GetDescendants(IEnumerable source, XName name, bool self) where T: XContainer {
            foreach (XContainer root in source) { 
                if (root != null) {
                    if (self) { 
                        XElement e = (XElement)root; 
                        if (name == null || e.name == name) yield return e;
                    } 
                    XNode n = root;
                    XContainer c = root;
                    while (true) {
                        if (c != null && c.content is XNode) { 
                            n = ((XNode)c.content).next;
                        } 
                        else { 
                            while (n != null && n != root && n == n.parent.content) n = n.parent;
                            if (n == null || n == root) break; 
                            n = n.next;
                        }
                        XElement e = n as XElement;
                        if (e != null && (name == null || e.name == name)) yield return e; 
                        c = e;
                    } 
                } 
            }
        } 

        static IEnumerable GetElements(IEnumerable source, XName name) where T: XContainer {
            foreach (XContainer root in source) {
                if (root != null) { 
                    XNode n = root.content as XNode;
                    if (n != null) { 
                        do { 
                            n = n.next;
                            XElement e = n as XElement; 
                            if (e != null && (name == null || e.name == name)) yield return e;
                        } while (n.parent == root && n != root.content);
                    }
                } 
            }
        } 
    } 

    internal class XNodeBuilder : XmlWriter 
    {
        List content;
        XContainer parent;
        XName attrName; 
        string attrValue;
        XContainer root; 
 
        public XNodeBuilder(XContainer container) {
            root = container; 
        }

        public override XmlWriterSettings Settings {
            get { 
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.ConformanceLevel = ConformanceLevel.Auto; 
                return settings; 
            }
        } 

        public override WriteState WriteState {
            get { throw new NotSupportedException(); } // nop
        } 

        public override void Close() { 
            root.Add(content); 
        }
 
        public override void Flush() {
        }

        public override string LookupPrefix(string namespaceName) { 
            throw new NotSupportedException(); // nop
        } 
 
        public override void WriteBase64(byte[] buffer, int index, int count) {
            throw new NotSupportedException(Res.GetString(Res.NotSupported_WriteBase64)); 
        }

        public override void WriteCData(string text) {
            AddNode(new XCData(text)); 
        }
 
        public override void WriteCharEntity(char ch) { 
            AddString(new string(ch, 1));
        } 

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

        public override void WriteComment(string text) { 
            AddNode(new XComment(text)); 
        }
 
        public override void WriteDocType(string name, string pubid, string sysid, string subset) {
            AddNode(new XDocumentType(name, pubid, sysid, subset));
        }
 
        public override void WriteEndAttribute() {
            XAttribute a = new XAttribute(attrName, attrValue); 
            attrName = null; 
            attrValue = null;
            if (parent != null) { 
                parent.Add(a);
            }
            else {
                Add(a); 
            }
        } 
 
        public override void WriteEndDocument() {
        } 

        public override void WriteEndElement() {
            parent = ((XElement)parent).parent;
        } 

        public override void WriteEntityRef(string name) { 
            switch (name) { 
                case "amp":
                    AddString("&"); 
                    break;
                case "apos":
                    AddString("'");
                    break; 
                case "gt":
                    AddString(">"); 
                    break; 
                case "lt":
                    AddString("<"); 
                    break;
                case "quot":
                    AddString("\"");
                    break; 
                default:
                    throw new NotSupportedException(Res.GetString(Res.NotSupported_WriteEntityRef)); 
            } 
        }
 
        public override void WriteFullEndElement() {
            XElement e = (XElement)parent;
            if (e.IsEmpty) {
                e.Add(string.Empty); 
            }
            parent = e.parent; 
        } 

        public override void WriteProcessingInstruction(string name, string text) { 
            if (name == "xml") {
                return;
            }
            AddNode(new XProcessingInstruction(name, text)); 
        }
 
        public override void WriteRaw(char[] buffer, int index, int count) { 
            AddString(new string(buffer, index, count));
        } 

        public override void WriteRaw(string data) {
            AddString(data);
        } 

        public override void WriteStartAttribute(string prefix, string localName, string namespaceName) { 
            if (prefix == null) throw new ArgumentNullException("prefix"); 
            attrName = XNamespace.Get(prefix.Length == 0 ? string.Empty : namespaceName).GetName(localName);
            attrValue = string.Empty; 
        }

        public override void WriteStartDocument() {
        } 

        public override void WriteStartDocument(bool standalone) { 
        } 

        public override void WriteStartElement(string prefix, string localName, string namespaceName) { 
            AddNode(new XElement(XNamespace.Get(namespaceName).GetName(localName)));
        }

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

        public override void WriteWhitespace(string ws) {
            AddString(ws); 
        }
 
        void Add(object o) { 
            if (content == null) {
                content = new List(); 
            }
            content.Add(o);
        }
 
        void AddNode(XNode n) {
            if (parent != null) { 
                parent.Add(n); 
            }
            else { 
                Add(n);
            }
            XContainer c = n as XContainer;
            if (c != null) { 
                parent = c;
            } 
        } 

        void AddString(string s) { 
            if (s == null) {
                return;
            }
            if (attrValue != null) { 
                attrValue += s;
            } 
            else if (parent != null) { 
                parent.Add(s);
            } 
            else {
                Add(s);
            }
        } 
    }
 
    internal class XNodeReader : XmlReader, IXmlLineInfo 
    {
        // The reader position is encoded by the tuple (source, parent). 
        // Lazy text uses (instance, parent element). Attribute value
        // uses (instance, parent attribute). End element uses (instance,
        // instance). Common XObject uses (instance, null).
        object source; 
        object parent;
        ReadState state; 
        XNode root; 
        XmlNameTable nameTable;
 
        internal XNodeReader(XNode node, XmlNameTable nameTable) {
            this.source = node;
            this.root = node;
            this.nameTable = nameTable != null ? nameTable : CreateNameTable(); 
        }
 
        public override int AttributeCount { 
            get {
                if (!IsInteractive) { 
                    return 0;
                }
                int count = 0;
                XElement e = GetElementInAttributeScope(); 
                if (e != null) {
                    XAttribute a = e.lastAttr; 
                    if (a != null) { 
                        do {
                            a = a.next; 
                            count++;
                        } while (a != e.lastAttr);
                    }
                } 
                return count;
            } 
        } 

        public override string BaseURI { 
            get {
                if (!IsInteractive) {
                    return string.Empty;
                } 
                XObject o = source as XObject;
                if (o != null) { 
                    return o.BaseUri; 
                }
                o = parent as XObject; 
                if (o != null) {
                    return o.BaseUri;
                }
                return string.Empty; 
            }
        } 
 
        public override int Depth {
            get { 
                if (!IsInteractive) {
                    return 0;
                }
                XObject o = source as XObject; 
                if (o != null) {
                    return GetDepth(o); 
                } 
                o = parent as XObject;
                if (o != null) { 
                    return GetDepth(o) + 1;
                }
                return 0;
            } 
        }
 
        static int GetDepth(XObject o) { 
            int depth = 0;
            while (o.parent != null) { 
                depth++;
                o = o.parent;
            }
            if (o is XDocument) { 
                depth--;
            } 
            return depth; 
        }
 
        public override bool EOF {
            get { return state == ReadState.EndOfFile; }
        }
 
        public override bool HasAttributes {
            get { 
                if (!IsInteractive) { 
                    return false;
                } 
                XElement e = GetElementInAttributeScope();
                return e != null && e.lastAttr != null;
            }
        } 

        public override bool HasValue { 
            get { 
                if (!IsInteractive) {
                    return false; 
                }
                XObject o = source as XObject;
                if (o != null) {
                    switch (o.NodeType) { 
                        case XmlNodeType.Attribute:
                        case XmlNodeType.Text: 
                        case XmlNodeType.CDATA: 
                        case XmlNodeType.Comment:
                        case XmlNodeType.ProcessingInstruction: 
                        case XmlNodeType.DocumentType:
                            return true;
                        default:
                            return false; 
                    }
                } 
                return true; 
            }
        } 

        public override bool IsEmptyElement {
            get {
                if (!IsInteractive) { 
                    return false;
                } 
                XElement e = source as XElement; 
                return e != null && e.IsEmpty;
            } 
        }

        public override string LocalName {
            get { return nameTable.Add(GetLocalName()); } 
        }
 
        string GetLocalName() { 
            if (!IsInteractive) {
                return string.Empty; 
            }
            XElement e = source as XElement;
            if (e != null) {
                return e.Name.LocalName; 
            }
            XAttribute a = source as XAttribute; 
            if (a != null) { 
                return a.Name.LocalName;
            } 
            XProcessingInstruction p = source as XProcessingInstruction;
            if (p != null) {
                return p.Target;
            } 
            XDocumentType n = source as XDocumentType;
            if (n != null) { 
                return n.Name; 
            }
            return string.Empty; 
        }

        public override string Name {
            get { 
                string prefix = GetPrefix();
                if (prefix.Length == 0) { 
                    return nameTable.Add(GetLocalName()); 
                }
                return nameTable.Add(string.Concat(prefix, ":", GetLocalName())); 
            }
        }

        public override string NamespaceURI { 
            get { return nameTable.Add(GetNamespaceURI()); }
        } 
 
        string GetNamespaceURI() {
            if (!IsInteractive) { 
                return string.Empty;
            }
            XElement e = source as XElement;
            if (e != null) { 
                return e.Name.NamespaceName;
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                string namespaceName = a.Name.NamespaceName; 
                if (namespaceName.Length == 0 && a.Name.LocalName == "xmlns") {
                    return XNamespace.xmlnsPrefixNamespace;
                }
                return namespaceName; 
            }
            return string.Empty; 
        } 

        public override XmlNameTable NameTable { 
            get { return nameTable; }
        }

        public override XmlNodeType NodeType { 
            get {
                if (!IsInteractive) { 
                    return XmlNodeType.None; 
                }
                XObject o = source as XObject; 
                if (o != null) {
                    if (IsEndElement) {
                        return XmlNodeType.EndElement;
                    } 
                    XmlNodeType nt = o.NodeType;
                    if (nt != XmlNodeType.Text) { 
                        return nt; 
                    }
                    if (o.parent != null && o.parent.parent == null && o.parent is XDocument) { 
                        return XmlNodeType.Whitespace;
                    }
                    return XmlNodeType.Text;
                } 
                if (parent is XDocument) {
                    return XmlNodeType.Whitespace; 
                } 
                return XmlNodeType.Text;
            } 
        }

        public override string Prefix {
            get { return nameTable.Add(GetPrefix()); } 
        }
 
        string GetPrefix() { 
            if (!IsInteractive) {
                return string.Empty; 
            }
            XElement e = source as XElement;
            if (e != null) {
                string prefix = e.GetPrefixOfNamespace(e.Name.Namespace); 
                if (prefix != null) {
                    return prefix; 
                } 
                return string.Empty;
            } 
            XAttribute a = source as XAttribute;
            if (a != null) {
                string prefix = a.GetPrefixOfNamespace(a.Name.Namespace);
                if (prefix != null) { 
                    return prefix;
                } 
            } 
            return string.Empty;
        } 

        public override ReadState ReadState {
            get { return state; }
        } 

        public override XmlReaderSettings Settings { 
            get { 
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.CheckCharacters = false; 
                return settings;
            }
        }
 
        public override string Value {
            get { 
                if (!IsInteractive) { 
                    return string.Empty;
                } 
                XObject o = source as XObject;
                if (o != null) {
                    switch (o.NodeType) {
                        case XmlNodeType.Attribute: 
                            return ((XAttribute)o).Value;
                        case XmlNodeType.Text: 
                        case XmlNodeType.CDATA: 
                            return ((XText)o).Value;
                        case XmlNodeType.Comment: 
                            return ((XComment)o).Value;
                        case XmlNodeType.ProcessingInstruction:
                            return ((XProcessingInstruction)o).Data;
                        case XmlNodeType.DocumentType: 
                            return ((XDocumentType)o).InternalSubset;
                        default: 
                            return string.Empty; 
                    }
                } 
                return (string)source;
            }
        }
 
        public override string XmlLang {
            get { 
                if (!IsInteractive) { 
                    return string.Empty;
                } 
                XElement e = GetElementInScope();
                if (e != null) {
                    XName name = XNamespace.Xml.GetName("lang");
                    do { 
                        XAttribute a = e.Attribute(name);
                        if (a != null) { 
                            return a.Value; 
                        }
                        e = e.parent as XElement; 
                    } while (e != null);
                }
                return string.Empty;
            } 
        }
 
        public override XmlSpace XmlSpace { 
            get {
                if (!IsInteractive) { 
                    return XmlSpace.None;
                }
                XElement e = GetElementInScope();
                if (e != null) { 
                    XName name = XNamespace.Xml.GetName("space");
                    do { 
                        XAttribute a = e.Attribute(name); 
                        if (a != null) {
                            switch (a.Value.Trim(new char[] {' ', '\t', '\n', '\r'})) { 
                                case "preserve":
                                    return XmlSpace.Preserve;
                                case "default":
                                    return XmlSpace.Default; 
                                default:
                                    break; 
                            } 
                        }
                        e = e.parent as XElement; 
                    } while (e != null);
                }
                return XmlSpace.None;
            } 
        }
 
        public override void Close() { 
            source = null;
            parent = null; 
            root = null;
            state = ReadState.Closed;
        }
 
        public override string GetAttribute(string name) {
            if (!IsInteractive) { 
                return null; 
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                string localName, namespaceName;
                GetNameInAttributeScope(name, e, out localName, out namespaceName);
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do { 
                        a = a.next; 
                        if (a.Name.LocalName == localName && a.Name.NamespaceName == namespaceName) {
                            return a.Value; 
                        }
                    } while (a != e.lastAttr);
                }
                return null; 
            }
            XDocumentType n = source as XDocumentType; 
            if (n != null) { 
                switch (name) {
                    case "PUBLIC": 
                        return n.PublicId;
                    case "SYSTEM":
                        return n.SystemId;
                } 
            }
            return null; 
        } 

        public override string GetAttribute(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return null;
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                if (localName == "xmlns") { 
                    if (namespaceName != null && namespaceName.Length == 0) { 
                        return null;
                    } 
                    if (namespaceName == XNamespace.xmlnsPrefixNamespace) {
                        namespaceName = string.Empty;
                    }
                } 
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && a.Name.NamespaceName == namespaceName) { 
                            return a.Value;
                        }
                    } while (a != e.lastAttr);
                } 
            }
            return null; 
        } 

        public override string GetAttribute(int index) { 
            if (!IsInteractive) {
                return null;
            }
            if (index < 0) { 
                return null;
            } 
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do {
                        a = a.next;
                        if (index-- == 0) { 
                            return a.Value;
                        } 
                    } while (a != e.lastAttr); 
                }
            } 
            return null;
        }

        public override string LookupNamespace(string prefix) { 
            if (!IsInteractive) {
                return null; 
            } 
            if (prefix == null) {
                return null; 
            }
            XElement e = GetElementInScope();
            if (e != null) {
                XNamespace ns = prefix.Length == 0 ? e.GetDefaultNamespace() : e.GetNamespaceOfPrefix(prefix); 
                if (ns != null) {
                    return nameTable.Add(ns.NamespaceName); 
                } 
            }
            return null; 
        }

        public override bool MoveToAttribute(string name) {
            if (!IsInteractive) { 
                return false;
            } 
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                string localName, namespaceName; 
                GetNameInAttributeScope(name, e, out localName, out namespaceName);
                XAttribute a = e.lastAttr;
                if (a != null) {
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && 
                            a.Name.NamespaceName == namespaceName) { 
                            source = a;
                            parent = null; 
                            return true;
                        }
                    } while (a != e.lastAttr);
                } 
            }
            return false; 
        } 

        public override bool MoveToAttribute(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return false;
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                if (localName == "xmlns") { 
                    if (namespaceName != null && namespaceName.Length == 0) { 
                        return false;
                    } 
                    if (namespaceName == XNamespace.xmlnsPrefixNamespace) {
                        namespaceName = string.Empty;
                    }
                } 
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && 
                            a.Name.NamespaceName == namespaceName) {
                            source = a;
                            parent = null;
                            return true; 
                        }
                    } while (a != e.lastAttr); 
                } 
            }
            return false; 
        }

        public override void MoveToAttribute(int index) {
            if (!IsInteractive) { 
                return;
            } 
            if (index < 0) throw new ArgumentOutOfRangeException("index"); 
            XElement e = GetElementInAttributeScope();
            if (e != null) { 
                XAttribute a = e.lastAttr;
                if (a != null) {
                    do {
                        a = a.next; 
                        if (index-- == 0) {
                            source = a; 
                            parent = null; 
                            return;
                        } 
                    } while (a != e.lastAttr);
                }
            }
            throw new ArgumentOutOfRangeException("index"); 
        }
 
        public override bool MoveToElement() { 
            if (!IsInteractive) {
                return false; 
            }
            XAttribute a = source as XAttribute;
            if (a == null) {
                a = parent as XAttribute; 
            }
            if (a != null) { 
                if (a.parent != null) { 
                    source = a.parent;
                    parent = null; 
                    return true;
                }
            }
            return false; 
        }
 
        public override bool MoveToFirstAttribute() { 
            if (!IsInteractive) {
                return false; 
            }
            XElement e = GetElementInAttributeScope();
            if (e != null) {
                if (e.lastAttr != null) { 
                    source = e.lastAttr.next;
                    return true; 
                } 
            }
            return false; 
        }

        public override bool MoveToNextAttribute() {
            if (!IsInteractive) { 
                return false;
            } 
            XElement e = source as XElement; 
            if (e != null) {
                if (IsEndElement) { 
                    return false;
                }
                if (e.lastAttr != null) {
                    source = e.lastAttr.next; 
                    return true;
                } 
                return false; 
            }
            XAttribute a = source as XAttribute; 
            if (a == null) {
                a = parent as XAttribute;
            }
            if (a != null) { 
                if (a.parent != null && ((XElement)a.parent).lastAttr != a) {
                    source = a.next; 
                    parent = null; 
                    return true;
                } 
            }
            return false;
        }
 
        public override bool Read() {
            switch (state) { 
                case ReadState.Initial: 
                    state = ReadState.Interactive;
                    XDocument d = source as XDocument; 
                    if (d != null) {
                        return ReadIntoDocument(d);
                    }
                    return true; 
                case ReadState.Interactive:
                    return Read(false); 
                default: 
                    return false;
            } 
        }

        public override bool ReadAttributeValue() {
            if (!IsInteractive) { 
                return false;
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return ReadIntoAttribute(a); 
            }
            return false;
        }
 
        public override bool ReadToDescendant(string localName, string namespaceName) {
            if (!IsInteractive) { 
                return false; 
            }
            MoveToElement(); 
            XElement c = source as XElement;
            if (c != null && !c.IsEmpty) {
                if (IsEndElement) {
                    return false; 
                }
                foreach (XElement e in c.Descendants()) { 
                    if (e.Name.LocalName == localName && 
                        e.Name.NamespaceName == namespaceName) {
                        source = e; 
                        return true;
                    }
                }
                IsEndElement = true; 
            }
            return false; 
        } 

        public override bool ReadToFollowing(string localName, string namespaceName) { 
            while (Read()) {
                XElement e = source as XElement;
                if (e != null) {
                    if (IsEndElement) continue; 
                    if (e.Name.LocalName == localName && e.Name.NamespaceName == namespaceName) {
                        return true; 
                    } 
                }
            } 
            return false;
        }

        public override bool ReadToNextSibling(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return false; 
            } 
            MoveToElement();
            if (source != root) { 
                XNode n = source as XNode;
                if (n != null) {
                    foreach (XElement e in n.ElementsAfterSelf()) {
                        if (e.Name.LocalName == localName && 
                            e.Name.NamespaceName == namespaceName) {
                            source = e; 
                            IsEndElement = false; 
                            return true;
                        } 
                    }
                    if (n.parent is XElement) {
                        source = n.parent;
                        IsEndElement = true; 
                        return false;
                    } 
                } 
                else {
                    if (parent is XElement) { 
                        source = parent;
                        parent = null;
                        IsEndElement = true;
                        return false; 
                    }
                } 
            } 
            return ReadToEnd();
        } 

        public override void ResolveEntity() {
        }
 
        public override void Skip() {
            if (!IsInteractive) { 
                return; 
            }
            Read(true); 
        }

        bool IXmlLineInfo.HasLineInfo() {
            IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo; 
            if (li != null) {
                return li.HasLineInfo(); 
            } 
            return false;
        } 

        int IXmlLineInfo.LineNumber {
            get {
                IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo; 
                if (li != null) {
                    return li.LineNumber; 
                } 
                return 0;
            } 
        }

        int IXmlLineInfo.LinePosition {
            get { 
                IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo;
                if (li != null) { 
                    return li.LinePosition; 
                }
                return 0; 
            }
        }

        bool IsEndElement { 
            get { return parent == source; }
            set { parent = value ? source : null; } 
        } 

        bool IsInteractive { 
            get { return state == ReadState.Interactive; }
        }

        static XmlNameTable CreateNameTable() { 
            XmlNameTable nameTable = new NameTable();
            nameTable.Add(string.Empty); 
            nameTable.Add(XNamespace.xmlnsPrefixNamespace); 
            nameTable.Add(XNamespace.xmlPrefixNamespace);
            return nameTable; 
        }

        XElement GetElementInAttributeScope() {
            XElement e = source as XElement; 
            if (e != null) {
                if (IsEndElement) { 
                    return null; 
                }
                return e; 
            }
            XAttribute a = source as XAttribute;
            if (a != null) {
                return (XElement)a.parent; 
            }
            a = parent as XAttribute; 
            if (a != null) { 
                return (XElement)a.parent;
            } 
            return null;
        }

        XElement GetElementInScope() { 
            XElement e = source as XElement;
            if (e != null) { 
                return e; 
            }
            XNode n = source as XNode; 
            if (n != null) {
                return n.parent as XElement;
            }
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return (XElement)a.parent; 
            } 
            e = parent as XElement;
            if (e != null) { 
                return e;
            }
            a = parent as XAttribute;
            if (a != null) { 
                return (XElement)a.parent;
            } 
            return null; 
        }
 
        static void GetNameInAttributeScope(string qualifiedName, XElement e, out string localName, out string namespaceName) {
            if (qualifiedName != null && qualifiedName.Length != 0) {
                int i = qualifiedName.IndexOf(':');
                if (i != 0 && i != qualifiedName.Length - 1) { 
                    if (i == -1) {
                        localName = qualifiedName; 
                        namespaceName = string.Empty; 
                        return;
                    } 
                    XNamespace ns = e.GetNamespaceOfPrefix(qualifiedName.Substring(0, i));
                    if (ns != null) {
                        localName = qualifiedName.Substring(i + 1, qualifiedName.Length - i - 1);
                        namespaceName = ns.NamespaceName; 
                        return;
                    } 
                } 
            }
            localName = null; 
            namespaceName = null;
        }

        bool Read(bool skipContent) { 
            XElement e = source as XElement;
            if (e != null) { 
                if (e.IsEmpty || IsEndElement || skipContent) { 
                    return ReadOverNode(e);
                } 
                return ReadIntoElement(e);
            }
            XNode n = source as XNode;
            if (n != null) { 
                return ReadOverNode(n);
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return ReadOverAttribute(a, skipContent); 
            }
            return ReadOverText(skipContent);
        }
 
        bool ReadIntoDocument(XDocument d) {
            XNode n = d.content as XNode; 
            if (n != null) { 
                source = n.next;
                return true; 
            }
            string s = d.content as string;
            if (s != null) {
                if (s.Length > 0) { 
                    source = s;
                    parent = d; 
                    return true; 
                }
            } 
            return ReadToEnd();
        }

        bool ReadIntoElement(XElement e) { 
            XNode n = e.content as XNode;
            if (n != null) { 
                source = n.next; 
                return true;
            } 
            string s = e.content as string;
            if (s != null) {
                if (s.Length > 0) {
                    source = s; 
                    parent = e;
                } 
                else { 
                    source = e;
                    IsEndElement = true; 
                }
                return true;
            }
            return ReadToEnd(); 
        }
 
        bool ReadIntoAttribute(XAttribute a) { 
            source = a.value;
            parent = a; 
            return true;
        }

        bool ReadOverAttribute(XAttribute a, bool skipContent) { 
            XElement e = (XElement)a.parent;
            if (e != null) { 
                if (e.IsEmpty || skipContent) { 
                    return ReadOverNode(e);
                } 
                return ReadIntoElement(e);
            }
            return ReadToEnd();
        } 

        bool ReadOverNode(XNode n) { 
            if (n == root) { 
                return ReadToEnd();
            } 
            XNode next = n.next;
            if (null == next || next == n || n == n.parent.content) {
                if (n.parent == null || (n.parent.parent == null && n.parent is XDocument)) {
                    return ReadToEnd(); 
                }
                source = n.parent; 
                IsEndElement = true; 
            }
            else { 
                source = next;
                IsEndElement = false;
            }
            return true; 
        }
 
        bool ReadOverText(bool skipContent) { 
            if (parent is XElement) {
                source = parent; 
                parent = null;
                IsEndElement = true;
                return true;
            } 
            if (parent is XAttribute) {
                XAttribute a = (XAttribute)parent; 
                parent = null; 
                return ReadOverAttribute(a, skipContent);
            } 
            return ReadToEnd();
        }

        bool ReadToEnd() { 
            state = ReadState.EndOfFile;
            return false; 
        } 
    }
 

#if !PRODUCTION_BUILD
    static class Res
    { 
        internal const string Argument_AddAttribute = "Argument_AddAttribute";
        internal const string Argument_AddNode = "Argument_AddNode"; 
        internal const string Argument_AddNonWhitespace = "Argument_AddNonWhitespace"; 
        internal const string Argument_ConvertToString = "Argument_ConvertToString";
        internal const string Argument_CreateNavigator = "Argument_CreateNavigator"; 
        internal const string Argument_InvalidExpandedName = "Argument_InvalidExpandedName";
        internal const string Argument_InvalidPIName = "Argument_InvalidPIName";
        internal const string Argument_InvalidPrefix = "Argument_InvalidPrefix";
        internal const string Argument_MustBeDerivedFrom = "Argument_MustBeDerivedFrom"; 
        internal const string Argument_NamespaceDeclarationPrefixed = "Argument_NamespaceDeclarationPrefixed";
        internal const string Argument_NamespaceDeclarationXml = "Argument_NamespaceDeclarationXml"; 
        internal const string Argument_NamespaceDeclarationXmlns = "Argument_NamespaceDeclarationXmlns"; 
        internal const string Argument_XObjectValue = "Argument_XObjectValue";
        internal const string InvalidOperation_BadNodeType = "InvalidOperation_BadNodeType"; 
        internal const string InvalidOperation_DocumentStructure = "InvalidOperation_DocumentStructure";
        internal const string InvalidOperation_DuplicateAttribute = "InvalidOperation_DuplicateAttribute";
        internal const string InvalidOperation_ExpectedEndOfFile = "InvalidOperation_ExpectedEndOfFile";
        internal const string InvalidOperation_ExpectedInteractive = "InvalidOperation_ExpectedInteractive"; 
        internal const string InvalidOperation_ExpectedNodeType = "InvalidOperation_ExpectedNodeType";
        internal const string InvalidOperation_ExternalCode = "InvalidOperation_ExternalCode"; 
        internal const string InvalidOperation_DeserializeInstance = "InvalidOperation_DeserializeInstance"; 
        internal const string InvalidOperation_MissingAncestor = "InvalidOperation_MissingAncestor";
        internal const string InvalidOperation_MissingParent = "InvalidOperation_MissingParent"; 
        internal const string InvalidOperation_MissingRoot = "InvalidOperation_MissingRoot";
        internal const string InvalidOperation_UnexpectedEvaluation = "InvalidOperation_UnexpectedEvaluation";
        internal const string InvalidOperation_UnexpectedNodeType = "InvalidOperation_UnexpectedNodeType";
        internal const string InvalidOperation_UnresolvedEntityReference = "InvalidOperation_UnresolvedEntityReference"; 
        internal const string InvalidOperation_WriteAttribute = "InvalidOperation_WriteAttribute";
        internal const string NotSupported_CheckValidity = "NotSupported_CheckValidity"; 
        internal const string NotSupported_MoveToId = "NotSupported_MoveToId"; 
        internal const string NotSupported_WriteBase64 = "NotSupported_WriteBase64";
        internal const string NotSupported_WriteEntityRef = "NotSupported_WriteEntityRef"; 

        public static string GetString(string name) {
            switch (name) {
                case Argument_AddAttribute: 
                    return "An attribute cannot be added to content.";
                case Argument_AddNode: 
                    return "A node of type {0} cannot be added to content."; 
                case Argument_AddNonWhitespace:
                    return "Non white space characters cannot be added to content."; 
                case Argument_ConvertToString:
                    return "The argument cannot be converted to a string.";
                case Argument_CreateNavigator:
                    return "This XPathNavigator cannot be created on a node of type {0}."; 
                case Argument_InvalidExpandedName:
                    return "'{0}' is an invalid expanded name."; 
                case Argument_InvalidPIName: 
                    return "'{0}' is an invalid name for a processing instruction.";
                case Argument_InvalidPrefix: 
                    return "'{0}' is an invalid prefix.";
                case Argument_MustBeDerivedFrom:
                    return "The argument must be derived from {0}.";
                case Argument_NamespaceDeclarationPrefixed: 
                     return "The prefix '{0}' cannot be bound to the empty namespace name.";
                case Argument_NamespaceDeclarationXml: 
                     return "The prefix 'xml' is bound to the namespace name 'http://www.w3.org/XML/1998/namespace'. Other prefixes must not be bound to this namespace name, and it must not be declared as the default namespace."; 
                case Argument_NamespaceDeclarationXmlns:
                     return "The prefix 'xmlns' is bound to the namespace name 'http://www.w3.org/2000/xmlns/'. It must not be declared. Other prefixes must not be bound to this namespace name, and it must not be declared as the default namespace."; 
                case Argument_XObjectValue:
                    return "An XObject cannot be used as a value.";
                case InvalidOperation_BadNodeType:
                    return "This operation is not valid on a node of type {0}."; 
                case InvalidOperation_DocumentStructure:
                    return "This operation would create an incorrectly structured document."; 
                case InvalidOperation_DuplicateAttribute: 
                    return "Duplicate attribute.";
                case InvalidOperation_ExpectedEndOfFile: 
                    return "The XmlReader state should be EndOfFile after this operation.";
                case InvalidOperation_ExpectedInteractive:
                    return "The XmlReader state should be Interactive.";
                case InvalidOperation_ExpectedNodeType: 
                    return "The XmlReader must be on a node of type {0} instead of a node of type {1}.";
                case InvalidOperation_ExternalCode: 
                    return "This operation was corrupted by external code."; 
                case InvalidOperation_DeserializeInstance:
                    return "This instance cannot be deserialized."; 
                case InvalidOperation_MissingAncestor:
                    return "A common ancestor is missing.";
                case InvalidOperation_MissingParent:
                    return "The parent is missing."; 
                case InvalidOperation_MissingRoot:
                    return "The root element is missing."; 
                case InvalidOperation_UnexpectedEvaluation: 
                    return "The XPath expression evaluated to unexpected type {0}.";
                case InvalidOperation_UnexpectedNodeType: 
                    return "The XmlReader should not be on a node of type {0}.";
                case InvalidOperation_UnresolvedEntityReference:
                    return "The XmlReader cannot resolve entity references.";
                case InvalidOperation_WriteAttribute: 
                    return "An attribute cannot be written after content.";
                case NotSupported_CheckValidity: 
                    return "This XPathNavigator does not support XSD validation."; 
                case NotSupported_MoveToId:
                    return "This XPathNavigator does not support IDs."; 
                case NotSupported_WriteBase64:
                    return "This XmlWriter does not support base64 encoded data.";
                case NotSupported_WriteEntityRef:
                    return "This XmlWriter does not support entity references."; 
            }
            return null; 
        } 

        public static string GetString(string name, params object[] args) { 
            string res = GetString(name);
            if (args == null || args.Length == 0) return res;
            return string.Format(CultureInfo.CurrentCulture, res, args);
        } 
    }
#endif 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; 
using System.IO;
using System.Linq; 
using System.Runtime.Serialization; 
using System.Text;
using System.Threading; 
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using CultureInfo = System.Globalization.CultureInfo; 

[module:SuppressMessage("Microsoft.Performance","CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xml.Linq.Res.#GetObject(System.String)", Justification="Build generated code.")] 
[module:SuppressMessage("Microsoft.Performance","CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xml.Linq.Res.#get_Resources()", Justification="Build generated code.")] 

namespace System.Xml.Linq 
{
    /// 
    /// Represents a name of an XML element or attribute. This class cannot be inherited.
    ///  
    [Serializable()]
    [SuppressMessage("Microsoft.Usage", "CA2229:ImplementSerializationConstructors", Justification = "Deserialization handled by NameSerializer.")] 
    public sealed class XName : IEquatable, ISerializable 
    {
        XNamespace ns; 
        string localName;
        int hashCode;

        ///  
        /// Constructor, internal so that external users must go through the Get() method to create an XName.
        ///  
        internal XName(XNamespace ns, string localName) { 
            this.ns = ns;
            this.localName = XmlConvert.VerifyNCName(localName); 
            this.hashCode = ns.GetHashCode() ^ localName.GetHashCode();
        }

        ///  
        /// Gets the local (unqualified) part of the name.
        ///  
        ///  
        public string LocalName {
            get { return localName; } 
        }

        /// 
        /// Gets the namespace of the name. 
        /// 
        public XNamespace Namespace { 
            get { return ns; } 
        }
 
        /// 
        /// Gets the namespace name part of the name.
        /// 
        public string NamespaceName { 
            get { return ns.NamespaceName; }
        } 
 
        /// 
        /// Returns the expanded XML name in the format: {namespaceName}localName. 
        /// 
        public override string ToString() {
            if (ns.NamespaceName.Length == 0) return localName;
            return "{" + ns.NamespaceName + "}" + localName; 
        }
 
        ///  
        /// Returns an  object created from the specified expanded name.
        ///  
        /// 
        /// A string containing an expanded XML name in the format: {namespace}localname.
        /// 
        ///  
        /// An  object constructed from the specified expanded name.
        ///  
        public static XName Get(string expandedName) { 
            if (expandedName == null) throw new ArgumentNullException("expandedName");
            if (expandedName.Length == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidExpandedName, expandedName)); 
            if (expandedName[0] == '{') {
                int i = expandedName.LastIndexOf('}');
                if (i <= 1 || i == expandedName.Length - 1) throw new ArgumentException(Res.GetString(Res.Argument_InvalidExpandedName, expandedName));
                return XNamespace.Get(expandedName, 1, i - 1).GetName(expandedName, i + 1, expandedName.Length - i - 1); 
            }
            else { 
                return XNamespace.None.GetName(expandedName); 
            }
        } 

        /// 
        /// Returns an  object from a local name and a namespace.
        ///  
        /// A local (unqualified) name.
        /// An XML namespace. 
        /// An XName object created from the specified local name and namespace. 
        public static XName Get(string localName, string namespaceName) {
            return XNamespace.Get(namespaceName).GetName(localName); 
        }

        /// 
        /// Converts a string formatted as an expanded XML name ({namespace}localname) to an XName object. 
        /// 
        /// A string containing an expanded XML name in the format: {namespace}localname. 
        /// An XName object constructed from the expanded name. 
        [CLSCompliant(false)]
        public static implicit operator XName(string expandedName) { 
            return expandedName != null ? Get(expandedName) : null;
        }

        ///  
        /// Determines whether the specified  is equal to the current .
        ///  
        /// The XName to compare to the current XName. 
        /// 
        /// true if the specified  is equal to the current XName; otherwise false. 
        /// 
        /// 
        /// For two  objects to be equal, they must have the same expanded name.
        ///  
        public override bool Equals(object obj) {
            return (object)this == obj; 
        } 

        ///  
        /// Serves as a hash function for . GetHashCode is suitable
        /// for use in hashing algorithms and data structures like a hash table.
        /// 
        public override int GetHashCode() { 
            return hashCode;
        } 
 
        // The overloads of == and != are included to enable comparisons between
        // XName and string (e.g. element.Name == "foo"). C#'s predefined reference 
        // equality operators require one operand to be convertible to the type of
        // the other through reference conversions only and do not consider the
        // implicit conversion from string to XName.
 
        /// 
        /// Returns a value indicating whether two instances of  are equal. 
        ///  
        /// The first XName to compare.
        /// The second XName to compare. 
        /// true if left and right are equal; otherwise false.
        /// 
        /// This overload is included to enable the comparison between
        /// an instance of XName and string. 
        /// 
        public static bool operator ==(XName left, XName right) { 
            return (object)left == (object)right; 
        }
 
        /// 
        /// Returns a value indicating whether two instances of  are not equal.
        /// 
        /// The first XName to compare. 
        /// The second XName to compare.
        /// true if left and right are not equal; otherwise false. 
        ///  
        /// This overload is included to enable the comparison between
        /// an instance of XName and string. 
        /// 
        public static bool operator !=(XName left, XName right) {
            return (object)left != (object)right;
        } 

        ///  
        /// Indicates whether the current  is equal to 
        /// the specified 
        ///  
        /// The  to compare with the
        /// current 
        /// 
        /// Returns true if the current  is equal to 
        /// the specified . Returns false otherwise.
        ///  
        bool IEquatable.Equals(XName other) { 
            return (object)this == (object)other;
        } 

        /// 
        /// Populates a  with the data needed to
        /// serialize the  
        /// 
        /// The  to populate with data 
        /// The destination for this serialization 
        [System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityAction.LinkDemand, 
            Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
            if (info == null) throw new ArgumentNullException("info");
            info.AddValue("name", ToString()); 
            info.SetType(typeof(NameSerializer));
        } 
    } 

    [Serializable()] 
    internal sealed class NameSerializer : IObjectReference, ISerializable
    {
        string expandedName;
 
        private NameSerializer(SerializationInfo info, StreamingContext context) {
            if (info == null) throw new ArgumentNullException("info"); 
            expandedName = info.GetString("name"); 
        }
 
        object IObjectReference.GetRealObject(StreamingContext context) {
            return XName.Get(expandedName);
        }
 
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
            throw new NotSupportedException(); // nop 
        } 
    }
 
    /// 
    /// Represents an XML namespace. This class cannot be inherited.
    /// 
    public sealed class XNamespace 
    {
        internal const string xmlPrefixNamespace = "http://www.w3.org/XML/1998/namespace"; 
        internal const string xmlnsPrefixNamespace = "http://www.w3.org/2000/xmlns/"; 

        static XHashtable namespaces; 
        static WeakReference refNone;
        static WeakReference refXml;
        static WeakReference refXmlns;
 
        string namespaceName;
        int hashCode; 
        XHashtable names; 

        const int NamesCapacity = 8;           // Starting capacity of XName table, which must be power of 2 
        const int NamespacesCapacity = 32;     // Starting capacity of XNamespace table, which must be power of 2

        /// 
        /// Constructor, internal so that external users must go through the Get() method to create an XNamespace. 
        /// 
        internal XNamespace(string namespaceName) { 
            this.namespaceName = namespaceName; 
            this.hashCode = namespaceName.GetHashCode();
            names = new XHashtable(ExtractLocalName, NamesCapacity); 
        }

        /// 
        /// Gets the namespace name of the namespace. 
        /// 
        public string NamespaceName { 
            get { return namespaceName; } 
        }
 
        /// 
        /// Returns an XName object created from the current instance and the specified local name.
        /// 
        ///  
        /// The returned XName object is guaranteed to be atomic (i.e. the only one in the system for this
        /// particular expanded name). 
        ///  
        public XName GetName(string localName) {
            if (localName == null) throw new ArgumentNullException("localName"); 
            return GetName(localName, 0, localName.Length);
        }

        ///  
        /// Returns the namespace name of this .
        ///  
        /// A string value containing the namespace name. 
        public override string ToString() {
            return namespaceName; 
        }

        /// 
        /// Gets the XNamespace object that corresponds to no namespace. 
        /// 
        ///  
        /// If an element or attribute is in no namespace, its namespace 
        /// will be set to the namespace returned by this property.
        ///  
        public static XNamespace None {
            get {
                return EnsureNamespace(ref refNone, string.Empty);
            } 
        }
 
        ///  
        /// Gets the XNamespace object that corresponds to the xml uri (http://www.w3.org/XML/1998/namespace).
        ///  
        public static XNamespace Xml {
            get {
                return EnsureNamespace(ref refXml, xmlPrefixNamespace);
            } 
        }
 
        ///  
        /// Gets the XNamespace object that corresponds to the xmlns uri (http://www.w3.org/2000/xmlns/).
        ///  
        public static XNamespace Xmlns {
            get {
                return EnsureNamespace(ref refXmlns, xmlnsPrefixNamespace);
            } 
        }
 
        ///  
        /// Gets an XNamespace created from the specified namespace name.
        ///  
        /// 
        /// The returned XNamespace object is guaranteed to be atomic
        /// (i.e. the only one in the system for that particular namespace name).
        ///  
        public static XNamespace Get(string namespaceName) {
            if (namespaceName == null) throw new ArgumentNullException("namespaceName"); 
            return Get(namespaceName, 0, namespaceName.Length); 
        }
 
        /// 
        /// Converts a string containing a namespace name to an XNamespace.
        /// 
        /// A string containing the namespace name. 
        /// An XNamespace constructed from the namespace name string.
        [CLSCompliant(false)] 
        public static implicit operator XNamespace(string namespaceName) { 
            return namespaceName != null ? Get(namespaceName) : null;
        } 

        /// 
        /// Combines an  object with a local name to create an .
        ///  
        /// The namespace for the expanded name.
        /// The local name for the expanded name. 
        /// The new XName constructed from the namespace and local name. 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Functionality available via XNamespace.Get().")]
        public static XName operator +(XNamespace ns, string localName) { 
            if (ns == null) throw new ArgumentNullException("ns");
            return ns.GetName(localName);
        }
 
        /// 
        /// Determines whether the specified  is equal to the current . 
        ///  
        /// The XNamespace to compare to the current XNamespace.
        ///  
        /// true if the specified  is equal to the current XNamespace; otherwise false.
        /// 
        /// 
        /// For two  objects to be equal they must have the same 
        /// namespace name.
        ///  
        public override bool Equals(object obj) { 
            return (object)this == obj;
        } 

        /// 
        /// Serves as a hash function for . GetHashCode is suitable
        /// for use in hashing algorithms and data structures like a hash table. 
        /// 
        public override int GetHashCode() { 
            return hashCode; 
        }
 

        // The overloads of == and != are included to enable comparisons between
        // XNamespace and string (e.g. element.Name.Namespace == "foo"). C#'s
        // predefined reference equality operators require one operand to be 
        // convertible to the type of the other through reference conversions only
        // and do not consider the implicit conversion from string to XNamespace. 
 
        /// 
        /// Returns a value indicating whether two instances of  are equal. 
        /// 
        /// The first XNamespace to compare.
        /// The second XNamespace to compare.
        /// true if left and right are equal; otherwise false. 
        /// 
        /// This overload is included to enable the comparison between 
        /// an instance of XNamespace and string. 
        /// 
        public static bool operator ==(XNamespace left, XNamespace right) { 
            return (object)left == (object)right;
        }

        ///  
        /// Returns a value indicating whether two instances of  are not equal.
        ///  
        /// The first XNamespace to compare. 
        /// The second XNamespace to compare.
        /// true if left and right are not equal; otherwise false. 
        /// 
        /// This overload is included to enable the comparison between
        /// an instance of XNamespace and string.
        ///  
        public static bool operator !=(XNamespace left, XNamespace right) {
            return (object)left != (object)right; 
        } 

        ///  
        /// Returns an  created from this XNamespace  and a portion of the passed in
        /// local name parameter.  The returned XName object is guaranteed to be atomic (i.e. the only one in the system for
        /// this particular expanded name).
        ///  
        internal XName GetName(string localName, int index, int count) {
            Debug.Assert(index >= 0 && index <= localName.Length, "Caller should have checked that index was in bounds"); 
            Debug.Assert(count >= 0 && index + count <= localName.Length, "Caller should have checked that count was in bounds"); 

            // Attempt to get the local name from the hash table 
            XName name;
            if (names.TryGetValue(localName, index, count, out name))
                return name;
 
            // No local name has yet been added, so add it now
            return names.Add(new XName(this, localName.Substring(index, count))); 
        } 

        ///  
        /// Returns an  created from a portion of the passed in namespace name parameter.  The returned XNamespace
        /// object is guaranteed to be atomic (i.e. the only one in the system for this particular namespace name).
        /// 
        internal static XNamespace Get(string namespaceName, int index, int count) { 
            Debug.Assert(index >= 0 && index <= namespaceName.Length, "Caller should have checked that index was in bounds");
            Debug.Assert(count >= 0 && index + count <= namespaceName.Length, "Caller should have checked that count was in bounds"); 
 
            if (count == 0) return None;
 
            // Use CompareExchange to ensure that exactly one XHashtable is used to store namespaces
            if (namespaces == null)
                Interlocked.CompareExchange(ref namespaces, new XHashtable(ExtractNamespace, NamespacesCapacity), null);
 
            WeakReference refNamespace;
            XNamespace ns; 
 
            // Keep looping until a non-null namespace has been retrieved
            do { 
                // Attempt to get the WeakReference for the namespace from the hash table
                if (!namespaces.TryGetValue(namespaceName, index, count, out refNamespace)) {
                    // If it is not there, first determine whether it's a special namespace
                    if (count == xmlPrefixNamespace.Length && string.CompareOrdinal(namespaceName, index, xmlPrefixNamespace, 0, count) == 0) return Xml; 
                    if (count == xmlnsPrefixNamespace.Length && string.CompareOrdinal(namespaceName, index, xmlnsPrefixNamespace, 0, count) == 0) return Xmlns;
 
                    // Go ahead and create the namespace and add it to the table 
                    refNamespace = namespaces.Add(new WeakReference(new XNamespace(namespaceName.Substring(index, count))));
                } 

                ns = (refNamespace != null) ? (XNamespace) refNamespace.Target : null;
            }
            while (ns == null); 

            return ns; 
        } 

        ///  
        /// This function is used by the ]]> to extract the local name part from an XName.  The hash table
        /// uses the local name as the hash key.
        /// 
        private static string ExtractLocalName(XName n) { 
            Debug.Assert(n != null, "Null name should never exist here");
            return n.LocalName; 
        } 

        ///  
        /// This function is used by the ]]> to extract the XNamespace that the WeakReference is
        /// referencing.  In cases where the XNamespace has been cleaned up, this function returns null.
        /// 
        private static string ExtractNamespace(WeakReference r) { 
            XNamespace ns;
 
            if (r == null || (ns = (XNamespace) r.Target) == null) 
                return null;
 
            return ns.NamespaceName;
        }

        ///  
        /// Ensure that an XNamespace object for 'namespaceName' has been atomically created.  In other words, all outstanding
        /// references to this particular namespace, on any thread, must all be to the same object.  Care must be taken, 
        /// since other threads can be concurrently calling this method, and the target of a WeakReference can be cleaned up 
        /// at any time by the GC.
        ///  
        private static XNamespace EnsureNamespace(ref WeakReference refNmsp, string namespaceName) {
            WeakReference refOld;

            // Keep looping until a non-null namespace has been retrieved 
            while (true) {
                // Save refNmsp in local variable, so we can work on a value that will not be changed by another thread 
                refOld = refNmsp; 

                if (refOld != null) { 
                    // If the target of the WeakReference is non-null, then we're done--just return the value
                    XNamespace ns = (XNamespace) refOld.Target;
                    if (ns != null) return ns;
                } 

                // Either refNmsp is null, or its target is null, so update it 
                // Make sure to do this atomically, so that we can guarantee atomicity of XNamespace objects 
                Interlocked.CompareExchange(ref refNmsp, new WeakReference(new XNamespace(namespaceName)), refOld);
            } 
        }
    }

    ///  
    /// This is a thread-safe hash table which maps string keys to values of type TValue.  It is assumed that the string key is embedded in the hashed value
    /// and can be extracted via a call to ExtractKeyDelegate (in order to save space and allow cleanup of key if value is released due to a WeakReference 
    /// TValue releasing its target). 
    /// 
    ///  
    /// All methods on this class are thread-safe.
    ///
    /// When the hash table fills up, it is necessary to resize it and rehash all contents.  Because this can be expensive,
    /// a lock is taken, and one thread is responsible for the resize.  Other threads which need to add values must wait 
    /// for the resize to be complete.
    /// 
    /// Thread-Safety Notes 
    /// ===================
    /// 
    /// 1. Because performance and scalability are such a concern with the global name table, I have avoided the use of
    ///    BIFALOs (Big Fat Locks).  Instead, I use CompareExchange, Interlocked.Increment, memory barriers, atomic state objects,
    ///    etc. to avoid locks.  Any changes to code which accesses these variables should be carefully reviewed and tested,
    ///    as it can be *very* tricky.  In particular, if you don't understand the CLR memory model or if you don't know 
    ///    what a memory barrier is, DON'T attempt to modify this code.  A good discussion of these topics can be found at
    ///    . 
    /// 
    /// 2. Because I am not sure if the CLR spec has changed since versions 1.0/1.1, I am assuming the weak memory model that
    ///    is described in the ECMA spec, in which normal writes can be reordered.  This means I must introduce more memory 
    ///    barriers than otherwise would be necessary.
    ///
    /// 3. There are several thread-safety concepts and patterns I utilize in this code:
    ///      a. Publishing -- There are a small number of places where state is exposed, or published, to multiple threads. 
    ///                       These places are marked with the comment "PUBLISH", and are key locations to consider when
    ///                       reviewing the code for thread-safety. 
    /// 
    ///      b. Immutable objects -- Immutable objects initialize their fields once in their constructor and then never modify
    ///                              them again.  As long as care is taken to ensure that initial field values are visible to 
    ///                              other threads before publishing the immutable object itself, immutable objects are
    ///                              completely thread-safe.
    ///
    ///      c. Atomic state objects -- Locks typically are taken when several pieces of state must be updated atomically.  In 
    ///                                 other words, there is a window in which state is inconsistent, and that window must
    ///                                 be protected from view by locking.  However, if a new object is created each time state 
    ///                                 changes (or state changes substantially), then during creation the new object is only 
    ///                                 visible to a single thread.  Once construction is complete, an assignment (guaranteed
    ///                                 atomic) can replace the old state object with the new state object, thus publishing a 
    ///                                 consistent view to all threads.
    ///
    ///      d. Retry -- When several threads contend over shared state which only one is allowed to possess, it is possible
    ///                  to avoid locking by repeatedly attempting to acquire the shared state.  The CompareExchange method 
    ///                  is useful for atomically ensuring that only one thread succeeds, and other threads are notified that
    ///                  they must retry. 
    /// 
    /// 4. All variables which can be written by multiple threads are marked "SHARED STATE".
    ///  
    internal sealed class XHashtable
    {
        private XHashtableState state;                          // SHARED STATE: Contains all XHashtable state, so it can be atomically swapped when resizes occur
 
        private const int StartingHash = (5381 << 16) + 5381;   // Starting hash code value for string keys to be hashed
 
        ///  
        /// Prototype of function which is called to extract a string key value from a hashed value.
        /// Returns null if the hashed value is invalid (e.g. value has been released due to a WeakReference TValue being cleaned up). 
        /// 
        public delegate string ExtractKeyDelegate(TValue value);

        ///  
        /// Construct a new XHashtable with the specified starting capacity.
        ///  
        public XHashtable(ExtractKeyDelegate extractKey, int capacity) { 
            state = new XHashtableState(extractKey, capacity);
        } 

        /// 
        /// Get an existing value from the hash table.  Return false if no such value exists.
        ///  
        public bool TryGetValue(string key, int index, int count, out TValue value) {
            return state.TryGetValue(key, index, count, out value); 
        } 

        ///  
        /// Add a value to the hash table, hashed based on a string key embedded in it.  Return the added value (may be a different object than "value").
        /// 
        public TValue Add(TValue value) {
            TValue newValue; 

            // Loop until value is in hash table 
            while (true) { 
                // Add new value
                // XHashtableState.TryAdd returns false if hash table is not big enough 
                if (state.TryAdd(value, out newValue))
                    return newValue;

                // PUBLISH (state) 
                // Hash table was not big enough, so resize it.
                // We only want one thread to perform a resize, as it is an expensive operation 
                // First thread will perform resize; waiting threads will call Resize(), but should immediately 
                // return since there will almost always be space in the hash table resized by the first thread.
                lock (this) { 
                    XHashtableState newState = state.Resize();

                    // Use memory barrier to ensure that the resized XHashtableState object is fully constructed before it is assigned
                    Thread.MemoryBarrier(); 
                    state = newState;
                } 
            } 
        }
 
        /// 
        /// This class contains all the hash table state.  Rather than creating a bucket object, buckets are structs
        /// packed into an array.  Buckets with the same truncated hash code are linked into lists, so that collisions
        /// can be disambiguated. 
        /// 
        ///  
        /// Note that the "buckets" and "entries" arrays are never themselves written by multiple threads.  Instead, the 
        /// *contents* of the array are written by multiple threads.  Resizing the hash table does not modify these variables,
        /// or even modify the contents of these variables.  Instead, resizing makes an entirely new XHashtableState object 
        /// in which all entries are rehashed.  This strategy allows reader threads to continue finding values in the "old"
        /// XHashtableState, while writer threads (those that need to add a new value to the table) are blocked waiting for
        /// the resize to complete.
        ///  
        private sealed class XHashtableState {
            private int[] buckets;                  // Buckets contain indexes into entries array (bucket values are SHARED STATE) 
            private Entry[] entries;                // Entries contain linked lists of buckets (next pointers are SHARED STATE) 
            private int numEntries;                 // SHARED STATE: Current number of entries (including orphaned entries)
            private ExtractKeyDelegate extractKey;  // Delegate called in order to extract string key embedded in hashed TValue 

            private const int EndOfList = 0;        // End of linked list marker
            private const int FullList = -1;        // Indicates entries should not be added to end of linked list
 
            /// 
            /// Construct a new XHashtableState object with the specified capacity. 
            ///  
            public XHashtableState(ExtractKeyDelegate extractKey, int capacity) {
                Debug.Assert((capacity & (capacity - 1)) == 0, "capacity must be a power of 2"); 
                Debug.Assert(extractKey != null, "extractKey may not be null");

                // Initialize hash table data structures, with specified maximum capacity
                buckets = new int[capacity]; 
                entries = new Entry[capacity];
 
                // Save delegate 
                this.extractKey = extractKey;
            } 

            /// 
            /// If this table is not full, then just return "this".  Otherwise, create and return a new table with
            /// additional capacity, and rehash all values in the table. 
            /// 
            public XHashtableState Resize() { 
                // No need to resize if there are open entries 
                if (numEntries < buckets.Length)
                    return this; 

                int newSize = 0;

                // Determine capacity of resized hash table by first counting number of valid, non-orphaned entries 
                // As this count proceeds, close all linked lists so that no additional entries can be added to them
                for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { 
                    int entryIdx = buckets[bucketIdx]; 

                    if (entryIdx == EndOfList) { 
                        // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize
                        entryIdx = Interlocked.CompareExchange(ref buckets[bucketIdx], FullList, EndOfList);
                    }
 
                    // Loop until we've guaranteed that the list has been counted and closed to further adds
                    while (entryIdx > EndOfList) { 
                        // Count each valid entry 
                        if (extractKey(entries[entryIdx].Value) != null)
                            newSize++; 

                        if (entries[entryIdx].Next == EndOfList) {
                            // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize
                            entryIdx = Interlocked.CompareExchange(ref entries[entryIdx].Next, FullList, EndOfList); 
                        }
                        else { 
                            // Move to next entry in the list 
                            entryIdx = entries[entryIdx].Next;
                        } 
                    }
                    Debug.Assert(entryIdx == EndOfList, "Resize() should only be called by one thread");
                }
 
                // Double number of valid entries; if result is less than current capacity, then use current capacity
                if (newSize < buckets.Length / 2) { 
                    newSize = buckets.Length; 
                }
                else { 
                    newSize = buckets.Length * 2;

                    if (newSize < 0)
                        throw new OverflowException(); 
                }
 
                // Create new hash table with additional capacity 
                XHashtableState newHashtable = new XHashtableState(extractKey, newSize);
 
                // Rehash names (TryAdd will always succeed, since we won't fill the new table)
                // Do not simply walk over entries and add them to table, as that would add orphaned
                // entries.  Instead, walk the linked lists and add each name.
                for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { 
                    int entryIdx = buckets[bucketIdx];
                    TValue newValue; 
 
                    while (entryIdx > EndOfList) {
                        newHashtable.TryAdd(entries[entryIdx].Value, out newValue); 
                        Debug.Assert((object)entries[entryIdx].Value == (object)newValue);

                        entryIdx = entries[entryIdx].Next;
                    } 
                    Debug.Assert(entryIdx == FullList, "Linked list should have been closed when it was counted");
                } 
 
                return newHashtable;
            } 

            /// 
            /// Attempt to find "key" in the table.  If the key exists, return the associated value in "value" and
            /// return true.  Otherwise return false. 
            /// 
            public bool TryGetValue(string key, int index, int count, out TValue value) { 
                int hashCode = ComputeHashCode(key, index, count); 
                int entryIndex = 0;
 
                // If a matching entry is found, return its value
                if (FindEntry(hashCode, key, index, count, ref entryIndex)) {
                    value = entries[entryIndex].Value;
                    return true; 
                }
 
                // No matching entry found, so return false 
                value = default(TValue);
                return false; 
            }

            /// 
            /// Attempt to add "value" to the table, hashed by an embedded string key.  If a value having the same key already exists, 
            /// then return the existing value in "newValue".  Otherwise, return the newly added value in "newValue".
            /// 
            /// If the hash table is full, return false.  Otherwise, return true. 
            /// 
            public bool TryAdd(TValue value, out TValue newValue) { 
                int newEntry, entryIndex;
                string key;
                int hashCode;
 
                // Assume "value" will be added and returned as "newValue"
                newValue = value; 
 
                // Extract the key from the value.  If it's null, then value is invalid and does not need to be added to table.
                key = extractKey(value); 
                if (key == null)
                    return true;

                // Compute hash code over entire length of key 
                hashCode = ComputeHashCode(key, 0, key.Length);
 
                // Assume value is not yet in the hash table, and prepare to add it (if table is full, return false). 
                // Use the entry index returned from Increment, which will never be zero, as zero conflicts with EndOfList.
                // Although this means that the first entry will never be used, it avoids the need to initialize all 
                // starting buckets to the EndOfList value.
                newEntry = Interlocked.Increment(ref numEntries);
                if (newEntry < 0 || newEntry >= buckets.Length)
                    return false; 

                entries[newEntry].Value = value; 
                entries[newEntry].HashCode = hashCode; 

                // Ensure that all writes to the entry can't be reordered past this barrier (or other threads might see new entry 
                // in list before entry has been initialized!).
                Thread.MemoryBarrier();

                // Loop until a matching entry is found, a new entry is added, or linked list is found to be full 
                entryIndex = 0;
                while (!FindEntry(hashCode, key, 0, key.Length, ref entryIndex)) { 
                    // PUBLISH (buckets slot) 
                    // No matching entry found, so add the new entry to the end of the list ("entryIndex" is index of last entry)
                    if (entryIndex == 0) 
                        entryIndex = Interlocked.CompareExchange(ref buckets[hashCode & (buckets.Length - 1)], newEntry, EndOfList);
                    else
                        entryIndex = Interlocked.CompareExchange(ref entries[entryIndex].Next, newEntry, EndOfList);
 
                    // Return true only if the CompareExchange succeeded (happens when replaced value is EndOfList).
                    // Return false if the linked list turned out to be full because another thread is currently resizing 
                    // the hash table.  In this case, entries[newEntry] is orphaned (not part of any linked list) and the 
                    // Add needs to be performed on the new hash table.  Otherwise, keep looping, looking for new end of list.
                    if (entryIndex <= EndOfList) 
                        return entryIndex == EndOfList;
                }

                // Another thread already added the value while this thread was trying to add, so return that instance instead. 
                // Note that entries[newEntry] will be orphaned (not part of any linked list) in this case
                newValue = entries[entryIndex].Value; 
 
                return true;
            } 

            /// 
            /// Searches a linked list of entries, beginning at "entryIndex".  If "entryIndex" is 0, then search starts at a hash bucket instead.
            /// Each entry in the list is matched against the (hashCode, key, index, count) key.  If a matching entry is found, then its 
            /// entry index is returned in "entryIndex" and true is returned.  If no matching entry is found, then the index of the last entry
            /// in the list (or 0 if list is empty) is returned in "entryIndex" and false is returned. 
            ///  
            /// 
            /// This method has the side effect of removing invalid entries from the list as it is traversed. 
            /// 
            private bool FindEntry(int hashCode, string key, int index, int count, ref int entryIndex) {
                int previousIndex = entryIndex;
                int currentIndex; 

                // Set initial value of currentIndex to index of the next entry following entryIndex 
                if (previousIndex == 0) 
                    currentIndex = buckets[hashCode & (buckets.Length - 1)];
                else 
                    currentIndex = previousIndex;

                // Loop while not at end of list
                while (currentIndex > EndOfList) { 

                    // Check for matching hash code, then matching key 
                    if (entries[currentIndex].HashCode == hashCode) { 
                        string keyCompare = extractKey(entries[currentIndex].Value);
 
                        // If the key is invalid, then attempt to remove the current entry from the linked list.
                        // This is thread-safe in the case where the Next field points to another entry, since once a Next field points
                        // to another entry, it will never be modified to be EndOfList or FullList.
                        if (keyCompare == null) { 
                            if (entries[currentIndex].Next > EndOfList) {
                                // PUBLISH (buckets slot or entries slot) 
                                // Entry is invalid, so modify previous entry to point to its next entry 
                                entries[currentIndex].Value = default(TValue);
                                currentIndex = entries[currentIndex].Next; 

                                if (previousIndex == 0)
                                    buckets[hashCode & (buckets.Length - 1)] = currentIndex;
                                else 
                                    entries[previousIndex].Next = currentIndex;
 
                                continue; 
                            }
                        } 
                        else {
                            // Valid key, so compare keys
                            if (count == keyCompare.Length && string.CompareOrdinal(key, index, keyCompare, 0, count) == 0) {
                                // Found match, so return true and matching entry in list 
                                entryIndex = currentIndex;
                                return true; 
                            } 
                        }
                    } 

                    // Move to next entry
                    previousIndex = currentIndex;
                    currentIndex = entries[currentIndex].Next; 
                }
 
                // Return false and last entry in list 
                entryIndex = previousIndex;
                return false; 
            }

            /// 
            /// Compute hash code for a string key (index, count substring of "key").  The algorithm used is the same on used in NameTable.cs in System.Xml. 
            /// 
            private static int ComputeHashCode(string key, int index, int count) { 
                int hashCode = StartingHash; 
                int end = index + count;
                Debug.Assert(key != null, "key should have been checked previously for null"); 

                // Hash the key
                for (int i = index; i < end; i++)
                    hashCode += (hashCode << 7) ^ key[i]; 

                // Mix up hash code a bit more and clear the sign bit.  This code was taken from NameTable.cs in System.Xml. 
                hashCode -= hashCode >> 17; 
                hashCode -= hashCode >> 11;
                hashCode -= hashCode >> 5; 
                return hashCode & 0x7FFFFFFF;
            }

            ///  
            /// Hash table entry.  The "Value" and "HashCode" fields are filled during initialization, and are never changed.  The "Next"
            /// field is updated when a new entry is chained to this one, and therefore care must be taken to ensure that updates to 
            /// this field are thread-safe. 
            /// 
            private struct Entry 
            {
                public TValue Value;    // Hashed value
                public int HashCode;    // Hash code of string key (equal to extractKey(Value).GetHashCode())
                public int Next;        // SHARED STATE: Points to next entry in linked list 
            }
        } 
    } 

    ///  
    /// Represents a node or an attribute in an XML tree.
    /// 
    public abstract class XObject : IXmlLineInfo
    { 
        internal XContainer parent;
        internal object annotations; 
 
        internal XObject() { }
 
        /// 
        /// Get the BaseUri for this .
        /// 
        [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Back-compat with System.Xml.")] 
        public string BaseUri {
            get { 
                XObject o = this; 
                while (true) {
                    while (o != null && o.annotations == null) { 
                        o = o.parent;
                    }
                    if (o == null) break;
                    BaseUriAnnotation a = o.Annotation(); 
                    if (a != null) return a.baseUri;
                    o = o.parent; 
                } 
                return string.Empty;
            } 
        }

        /// 
        /// Gets the XDocument object for this . 
        /// 
        public XDocument Document { 
            get { 
                XObject n = this;
                while (n.parent != null) n = n.parent; 
                return n as XDocument;
            }
        }
 
        /// 
        /// Gets the node type for this . 
        ///  
        public abstract XmlNodeType NodeType { get; }
 
        /// 
        /// Gets the parent  of this .
        /// 
        ///  
        /// If this  has no parent , this property returns null.
        ///  
        public XElement Parent { 
            get { return parent as XElement; }
        } 

        /// 
        /// Adds an object to the annotation list of this .
        ///  
        /// The annotation to add.
        public void AddAnnotation(object annotation) { 
            if (annotation == null) throw new ArgumentNullException("annotation"); 
            if (annotations == null) {
                annotations = annotation is object[] ? new object[] { annotation } : annotation; 
            }
            else {
                object[] a = annotations as object[];
                if (a == null) { 
                    annotations = new object[] { annotations, annotation };
                } 
                else { 
                    int i = 0;
                    while (i < a.Length && a[i] != null) i++; 
                    if (i == a.Length) {
                        Array.Resize(ref a, i * 2);
                        annotations = a;
                    } 
                    a[i] = annotation;
                } 
            } 
        }
 
        /// 
        /// Returns the first annotation object of the specified type from the list of annotations
        /// of this .
        ///  
        /// The type of the annotation to retrieve.
        ///  
        /// The first matching annotation object, or null 
        /// if no annotation is the specified type.
        ///  
        public object Annotation(Type type) {
            if (type == null) throw new ArgumentNullException("type");
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) return annotations; 
                } 
                else {
                    for (int i = 0; i < a.Length; i++) { 
                        object obj = a[i];
                        if (obj == null) break;
                        if (type.IsInstanceOfType(obj)) return obj;
                    } 
                }
            } 
            return null; 
        }
 
        /// 
        /// Returns the first annotation object of the specified type from the list of annotations
        /// of this .
        ///  
        /// The type of the annotation to retrieve.
        ///  
        /// The first matching annotation object, or null if no annotation 
        /// is the specified type.
        ///  
        public T Annotation() where T : class
        {
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) return annotations as T;
                for (int i = 0; i < a.Length; i++) { 
                    object obj = a[i]; 
                    if (obj == null) break;
                    T result = obj as T; 
                    if (result != null) return result;
                }
            }
            return null; 
        }
 
        ///  
        /// Returns an enumerable collection of annotations of the specified type
        /// for this . 
        /// 
        /// The type of the annotations to retrieve.
        /// An enumerable collection of annotations for this XObject.
        public IEnumerable Annotations(Type type) { 
            if (type == null) throw new ArgumentNullException("type");
            return AnnotationsIterator(type); 
        } 

        IEnumerable AnnotationsIterator(Type type) { 
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) yield return annotations; 
                }
                else { 
                    for (int i = 0; i < a.Length; i++) { 
                        object obj = a[i];
                        if (obj == null) break; 
                        if (type.IsInstanceOfType(obj)) yield return obj;
                    }
                }
            } 
        }
 
        ///  
        /// Returns an enumerable collection of annotations of the specified type
        /// for this . 
        /// 
        /// The type of the annotations to retrieve.
        /// An enumerable collection of annotations for this XObject.
        public IEnumerable Annotations() where T : class { 
            if (annotations != null) {
                object[] a = annotations as object[]; 
                if (a == null) { 
                    T result = annotations as T;
                    if (result != null) yield return result; 
                }
                else {
                    for (int i = 0; i < a.Length; i++) {
                        object obj = a[i]; 
                        if (obj == null) break;
                        T result = obj as T; 
                        if (result != null) yield return result; 
                    }
                } 
            }
        }

        ///  
        /// Removes the annotations of the specified type from this .
        ///  
        /// The type of annotations to remove. 
        public void RemoveAnnotations(Type type) {
            if (type == null) throw new ArgumentNullException("type"); 
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) {
                    if (type.IsInstanceOfType(annotations)) annotations = null; 
                }
                else { 
                    int i = 0, j = 0; 
                    while (i < a.Length) {
                        object obj = a[i]; 
                        if (obj == null) break;
                        if (!type.IsInstanceOfType(obj)) a[j++] = obj;
                        i++;
                    } 
                    if (j == 0) {
                        annotations = null; 
                    } 
                    else {
                        while (j < i) a[j++] = null; 
                    }
                }
            }
        } 

        ///  
        /// Removes the annotations of the specified type from this . 
        /// 
        /// The type of annotations to remove. 
        public void RemoveAnnotations() where T : class {
            if (annotations != null) {
                object[] a = annotations as object[];
                if (a == null) { 
                    if (annotations is T) annotations = null;
                } 
                else { 
                    int i = 0, j = 0;
                    while (i < a.Length) { 
                        object obj = a[i];
                        if (obj == null) break;
                        if (!(obj is T)) a[j++] = obj;
                        i++; 
                    }
                    if (j == 0) { 
                        annotations = null; 
                    }
                    else { 
                        while (j < i) a[j++] = null;
                    }
                }
            } 
        }
 
        ///  
        /// Occurs when this  or any of its descendants have changed.
        ///  
        public event EventHandler Changed {
            add {
                if (value == null) return;
                XObjectChangeAnnotation a = Annotation(); 
                if (a == null) {
                    a = new XObjectChangeAnnotation(); 
                    AddAnnotation(a); 
                }
                a.changed += value; 
            }
            remove {
                if (value == null) return;
                XObjectChangeAnnotation a = Annotation(); 
                if (a == null) return;
                a.changed -= value; 
                if (a.changing == null && a.changed == null) { 
                    RemoveAnnotations();
                } 
            }
        }

        ///  
        /// Occurs when this  or any of its descendants are about to change.
        ///  
        public event EventHandler Changing { 
            add {
                if (value == null) return; 
                XObjectChangeAnnotation a = Annotation();
                if (a == null) {
                    a = new XObjectChangeAnnotation();
                    AddAnnotation(a); 
                }
                a.changing += value; 
            } 
            remove {
                if (value == null) return; 
                XObjectChangeAnnotation a = Annotation();
                if (a == null) return;
                a.changing -= value;
                if (a.changing == null && a.changed == null) { 
                    RemoveAnnotations();
                } 
            } 
        }
 
        bool IXmlLineInfo.HasLineInfo() {
            return Annotation() != null;
        }
 
        int IXmlLineInfo.LineNumber {
            get { 
                LineInfoAnnotation a = Annotation(); 
                if (a != null) return a.lineNumber;
                return 0; 
            }
        }

        int IXmlLineInfo.LinePosition { 
            get {
                LineInfoAnnotation a = Annotation(); 
                if (a != null) return a.linePosition; 
                return 0;
            } 
        }

        internal bool HasBaseUri {
            get { 
                return Annotation() != null;
            } 
        } 

        internal bool NotifyChanged(object sender, XObjectChangeEventArgs e) { 
            bool notify = false;
            XObject o = this;
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent;
                } 
                if (o == null) break; 
                XObjectChangeAnnotation a = o.Annotation();
                if (a != null) { 
                    notify = true;
                    if (a.changed != null) {
                        a.changed(sender, e);
                    } 
                }
                o = o.parent; 
            } 
            return notify;
        } 

        internal bool NotifyChanging(object sender, XObjectChangeEventArgs e) {
            bool notify = false;
            XObject o = this; 
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent; 
                }
                if (o == null) break; 
                XObjectChangeAnnotation a = o.Annotation();
                if (a != null) {
                    notify = true;
                    if (a.changing != null) { 
                        a.changing(sender, e);
                    } 
                } 
                o = o.parent;
            } 
            return notify;
        }

        internal void SetBaseUri(string baseUri) { 
            AddAnnotation(new BaseUriAnnotation(baseUri));
        } 
 
        internal void SetLineInfo(int lineNumber, int linePosition) {
            AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition)); 
        }

        internal bool SkipNotify() {
            XObject o = this; 
            while (true) {
                while (o != null && o.annotations == null) { 
                    o = o.parent; 
                }
                if (o == null) return true; 
                if (o.Annotations() != null) return false;
                o = o.parent;
            }
        } 
    }
 
    class BaseUriAnnotation 
    {
        internal string baseUri; 

        public BaseUriAnnotation(string baseUri) {
            this.baseUri = baseUri;
        } 
    }
 
    class LineInfoAnnotation 
    {
        internal int lineNumber; 
        internal int linePosition;

        public LineInfoAnnotation(int lineNumber, int linePosition) {
            this.lineNumber = lineNumber; 
            this.linePosition = linePosition;
        } 
    } 

    class XObjectChangeAnnotation 
    {
        internal EventHandler changing;
        internal EventHandler changed;
 
        public XObjectChangeAnnotation() {
        } 
    } 

    ///  
    /// Specifies the event type when an event is raised for an .
    /// 
    public enum XObjectChange
    { 
        /// 
        /// An  has been or will be added to an . 
        ///  
        Add,
 
        /// 
        /// An  has been or will be removed from an .
        /// 
        Remove, 

        ///  
        /// An  has been or will be renamed. 
        /// 
        Name, 

        /// 
        /// The value of an  has been or will be changed.
        /// There is a special case for elements. Change in the serialization 
        /// of an empty element (either from an empty tag to start/end tag
        /// pair or vice versa) raises this event. 
        ///  
        Value,
    } 

    /// 
    /// Provides data for the  and  events.
    ///  
    public class XObjectChangeEventArgs : EventArgs
    { 
        XObjectChange objectChange; 

        ///  
        /// Event argument for a  change event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")]
        public static readonly XObjectChangeEventArgs Add = new XObjectChangeEventArgs(XObjectChange.Add); 

        ///  
        /// Event argument for a  change event. 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")] 
        public static readonly XObjectChangeEventArgs Remove = new XObjectChangeEventArgs(XObjectChange.Remove);

        /// 
        /// Event argument for a  change event. 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")] 
        public static readonly XObjectChangeEventArgs Name = new XObjectChangeEventArgs(XObjectChange.Name); 

        ///  
        /// Event argument for a  change event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "False positive.")]
        public static readonly XObjectChangeEventArgs Value = new XObjectChangeEventArgs(XObjectChange.Value); 

        ///  
        /// Initializes a new instance of the  class. 
        /// 
        public XObjectChangeEventArgs(XObjectChange objectChange) { 
            this.objectChange = objectChange;
        }

        ///  
        /// Gets the type () of change.
        ///  
        public XObjectChange ObjectChange { 
            get { return objectChange; }
        } 
    }

    /// 
    /// Represents nodes (elements, comments, document type, processing instruction, 
    /// and text nodes) in the XML tree.
    ///  
    ///  
    /// Nodes in the XML tree consist of objects of the following classes:
    /// , 
    /// ,
    /// ,
    /// ,
    /// , 
    /// 
    /// Note that an  is not an . 
    ///  
    public abstract class XNode : XObject
    { 
        static XNodeDocumentOrderComparer documentOrderComparer;
        static XNodeEqualityComparer equalityComparer;

        internal XNode next; 

        internal XNode() { } 
 
        /// 
        /// Gets the next sibling node of this node. 
        /// 
        /// 
        /// If this property does not have a parent, or if there is no next node,
        /// then this property returns null. 
        /// 
        public XNode NextNode { 
            get { 
                return parent == null || this == parent.content ? null : next;
            } 
        }

        /// 
        /// Gets the previous sibling node of this node. 
        /// 
        ///  
        /// If this property does not have a parent, or if there is no previous node, 
        /// then this property returns null.
        ///  
        public XNode PreviousNode {
            get {
                if (parent == null) return null;
                XNode n = ((XNode)parent.content).next; 
                XNode p = null;
                while (n != this) { 
                    p = n; 
                    n = n.next;
                } 
                return p;
            }
        }
 
        /// 
        /// Gets a comparer that can compare the relative position of two nodes. 
        ///  
        public static XNodeDocumentOrderComparer DocumentOrderComparer {
            get { 
                if (documentOrderComparer == null) documentOrderComparer = new XNodeDocumentOrderComparer();
                return documentOrderComparer;
            }
        } 

        ///  
        /// Gets a comparer that can compare two nodes for value equality. 
        /// 
        public static XNodeEqualityComparer EqualityComparer { 
            get {
                if (equalityComparer == null) equalityComparer = new XNodeEqualityComparer();
                return equalityComparer;
            } 
        }
 
        ///  
        /// Adds the specified content immediately after this node. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects,
        /// or null.
        /// 
        ///  
        /// Adds the specified content immediately after this node.
        ///  
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added after this node. 
        /// 
        /// 
        /// Thrown if the parent is null.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void AddAfterSelf(object content) { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            new Inserter(parent, this).Add(content);
        }
 
        /// 
        /// Adds the specified content immediately after this node. 
        ///  
        /// 
        /// A parameter list of content objects. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        ///  
        /// Thrown if the parent is null. 
        /// 
        public void AddAfterSelf(params object[] content) { 
            AddAfterSelf((object)content);
        }

        ///  
        /// Adds the specified content immediately before this node. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, 
        /// or null.
        ///  
        /// 
        /// Adds the specified content immediately before this node.
        /// 
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added after this node. 
        ///  
        /// 
        /// Thrown if the parent is null. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void AddBeforeSelf(object content) { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent)); 
            XNode p = (XNode)parent.content;
            while (p.next != this) p = p.next; 
            if (p == parent.content) p = null;
            new Inserter(parent, p).Add(content);
        }
 
        /// 
        /// Adds the specified content immediately before this node. 
        ///  
        /// 
        /// A parameter list of content objects. 
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        ///  
        /// Thrown if the parent is null. 
        /// 
        public void AddBeforeSelf(params object[] content) { 
            AddBeforeSelf((object)content);
        }

        ///  
        /// Returns an collection of the ancestor elements for this node.
        /// Optionally an node name can be specified to filter for a specific ancestor element. 
        ///  
        /// 
        /// Returns a collection of the ancestor elements of this node. 
        /// 
        /// 
        /// The ancestor elements of this node.
        ///  
        /// 
        /// This method will not return itself in the results. 
        ///  
        public IEnumerable Ancestors() {
            return GetAncestors(null, false); 
        }

        /// 
        /// Returns a collection of the ancestor elements of this node with the specified name. 
        /// 
        ///  
        /// The name of the ancestor elements to find. 
        /// 
        ///  
        /// A collection of the ancestor elements of this node with the specified name.
        /// 
        /// 
        /// This method will not return itself in the results. 
        /// 
        public IEnumerable Ancestors(XName name) { 
            return name != null ? GetAncestors(name, false) : XElement.EmptySequence; 
        }
 
        /// 
        /// Compares two nodes to determine their relative XML document order.
        /// 
        /// First node to compare. 
        /// Second node to compare.
        ///  
        /// 0 if the nodes are equal; -1 if n1 is before n2; 1 if n1 is after n2. 
        /// 
        ///  
        /// Thrown if the two nodes do not share a common ancestor.
        /// 
        [SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Reviewed.")]
        public static int CompareDocumentOrder(XNode n1, XNode n2) { 
            if (n1 == n2) return 0;
            if (n1 == null) return -1; 
            if (n2 == null) return 1; 
            if (n1.parent != n2.parent) {
                int height = 0; 
                XNode p1 = n1;
                while (p1.parent != null) {
                    p1 = p1.parent;
                    height++; 
                }
                XNode p2 = n2; 
                while (p2.parent != null) { 
                    p2 = p2.parent;
                    height--; 
                }
                if (p1 != p2) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingAncestor));
                if (height < 0) {
                    do { 
                        n2 = n2.parent;
                        height++; 
                    } while (height != 0); 
                    if (n1 == n2) return -1;
                } 
                else if (height > 0) {
                    do {
                        n1 = n1.parent;
                        height--; 
                    } while (height != 0);
                    if (n1 == n2) return 1; 
                } 
                while (n1.parent != n2.parent) {
                    n1 = n1.parent; 
                    n2 = n2.parent;
                }
            }
            else if (n1.parent == null) { 
                throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingAncestor));
            } 
            XNode n = (XNode)n1.parent.content; 
            while (true) {
                n = n.next; 
                if (n == n1) return -1;
                if (n == n2) return 1;
            }
        } 

        ///  
        /// Creates an  for the node. 
        /// 
        /// An  that can be used to read the node and its descendants. 
        public XmlReader CreateReader() {
            return new XNodeReader(this, null);
        }
 
        /// 
        /// Returns a collection of the sibling nodes after this node, in document order. 
        ///  
        /// 
        /// This method only includes sibling nodes in the returned collection. 
        /// 
        /// The nodes after this node.
        public IEnumerable NodesAfterSelf() {
            XNode n = this; 
            while (n.parent != null && n != n.parent.content) {
                n = n.next; 
                yield return n; 
            }
        } 

        /// 
        /// Returns a collection of the sibling nodes before this node, in document order.
        ///  
        /// 
        /// This method only includes sibling nodes in the returned collection. 
        ///  
        /// The nodes after this node.
        public IEnumerable NodesBeforeSelf() { 
            if (parent != null) {
                XNode n = (XNode)parent.content;
                do {
                    n = n.next; 
                    if (n == this) break;
                    yield return n; 
                } while (parent != null && parent == n.parent); 
            }
        } 

        /// 
        /// Returns a collection of the sibling element nodes after this node, in document order.
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        ///  
        /// The element nodes after this node.
        public IEnumerable ElementsAfterSelf() { 
            return GetElementsAfterSelf(null);
        }

        ///  
        /// Returns a collection of the sibling element nodes with the specified name
        /// after this node, in document order. 
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        /// 
        /// The element nodes after this node with the specified name.
        /// The name of elements to enumerate.
        public IEnumerable ElementsAfterSelf(XName name) { 
            return name != null ? GetElementsAfterSelf(name) : XElement.EmptySequence;
        } 
 
        /// 
        /// Returns a collection of the sibling element nodes before this node, in document order. 
        /// 
        /// 
        /// This method only includes sibling element nodes in the returned collection.
        ///  
        /// The element nodes before this node.
        public IEnumerable ElementsBeforeSelf() { 
            return GetElementsBeforeSelf(null); 
        }
 
        /// 
        /// Returns a collection of the sibling element nodes with the specified name
        /// before this node, in document order.
        ///  
        /// 
        /// This method only includes sibling element nodes in the returned collection. 
        ///  
        /// The element nodes before this node with the specified name.
        /// The name of elements to enumerate. 
        public IEnumerable ElementsBeforeSelf(XName name) {
            return name != null ? GetElementsBeforeSelf(name) : XElement.EmptySequence;
        }
 
        /// 
        /// Determines if the current node appears after a specified node 
        /// in terms of document order. 
        /// 
        /// The node to compare for document order. 
        /// True if this node appears after the specified node; false if not.
        public bool IsAfter(XNode node) {
            return CompareDocumentOrder(this, node) > 0;
        } 

        ///  
        /// Determines if the current node appears before a specified node 
        /// in terms of document order.
        ///  
        /// The node to compare for document order.
        /// True if this node appears before the specified node; false if not.
        public bool IsBefore(XNode node) {
            return CompareDocumentOrder(this, node) < 0; 
        }
 
        ///  
        /// Creates an  from an .
        /// The runtime type of the node is determined by the node type 
        /// () of the first node encountered
        /// in the reader.
        /// 
        /// An  positioned at the node to read into this . 
        /// An  that contains the nodes read from the reader.
        ///  
        /// Thrown if the  is not positioned on a recognized node type. 
        /// 
        public static XNode ReadFrom(XmlReader reader) { 
            if (reader == null) throw new ArgumentNullException("reader");
            if (reader.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive));
            switch (reader.NodeType) {
                case XmlNodeType.Text: 
                case XmlNodeType.SignificantWhitespace:
                case XmlNodeType.Whitespace: 
                    return new XText(reader); 
                case XmlNodeType.CDATA:
                    return new XCData(reader); 
                case XmlNodeType.Comment:
                    return new XComment(reader);
                case XmlNodeType.DocumentType:
                    return new XDocumentType(reader); 
                case XmlNodeType.Element:
                    return new XElement(reader); 
                case XmlNodeType.ProcessingInstruction: 
                    return new XProcessingInstruction(reader);
                default: 
                    throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, reader.NodeType));
            }
        }
 
        /// 
        /// Removes this XNode from the underlying XML tree. 
        ///  
        /// 
        /// Thrown if the parent is null. 
        /// 
        public void Remove() {
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            parent.RemoveNode(this); 
        }
 
        ///  
        /// Replaces this node with the specified content. The
        /// content can be simple content, a collection of 
        /// content objects, a parameter list of content objects,
        /// or null.
        /// 
        ///  
        /// Replaces the content of this .
        ///  
        /// Content that replaces this node. 
        public void ReplaceWith(object content) {
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent)); 
            XContainer c = parent;
            XNode p = (XNode)parent.content;
            while (p.next != this) p = p.next;
            if (p == parent.content) p = null; 
            parent.RemoveNode(this);
            if (p != null && p.parent != c) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
            new Inserter(c, p).Add(content); 
        }
 
        /// 
        /// Replaces this node with the specified content.
        /// 
        /// Content that replaces this node. 
        public void ReplaceWith(params object[] content) {
            ReplaceWith((object)content); 
        } 

        ///  
        /// Provides the formatted XML text representation.
        /// 
        /// A formatted XML string.
        public override string ToString() { 
            return GetXmlString(SaveOptions.None);
        } 
 
        /// 
        /// Provides the XML text representation. 
        /// 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        /// An XML string.
        public string ToString(SaveOptions options) { 
            return GetXmlString(options); 
        }
 
        /// 
        /// Compares the values of two nodes, including the values of all descendant nodes.
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// true if the nodes are equal, false otherwise. 
        ///  
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two  objects of different types are never equal. Two 
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of equal content nodes. 
        /// Two s are equal if their root nodes are equal. Two
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same 
        /// target and data. Two  nodes are equal if the have the
        /// same name, public id, system id, and internal subset. 
        [SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Reviewed.")]
        public static bool DeepEquals(XNode n1, XNode n2) {
            if (n1 == n2) return true;
            if (n1 == null || n2 == null) return false; 
            return n1.DeepEquals(n2);
        } 
 
        /// 
        /// Write the current node to an . 
        /// 
        /// The  to write the current node into.
        public abstract void WriteTo(XmlWriter writer);
 
        internal virtual void AppendText(StringBuilder sb) {
        } 
 
        internal abstract XNode CloneNode();
 
        internal abstract bool DeepEquals(XNode node);

        internal IEnumerable GetAncestors(XName name, bool self) {
            XElement e = (self ? this : parent) as XElement; 
            while (e != null) {
                if (name == null || e.name == name) yield return e; 
                e = e.parent as XElement; 
            }
        } 

        IEnumerable GetElementsAfterSelf(XName name) {
            XNode n = this;
            while (n.parent != null && n != n.parent.content) { 
                n = n.next;
                XElement e = n as XElement; 
                if (e != null && (name == null || e.name == name)) yield return e; 
            }
        } 

        IEnumerable GetElementsBeforeSelf(XName name) {
            if (parent != null) {
                XNode n = (XNode)parent.content; 
                do {
                    n = n.next; 
                    if (n == this) break; 
                    XElement e = n as XElement;
                    if (e != null && (name == null || e.name == name)) yield return e; 
                } while (parent != null && parent == n.parent);
            }
        }
 
        internal abstract int GetDeepHashCode();
 
        // The settings simulate a non-validating processor with the external 
        // entity resolution disabled. The processing of the internal subset is
        // enabled by default. In order to prevent DoS attacks, the expanded 
        // size of the internal subset is limited to 10 million characters.
        internal static XmlReaderSettings GetXmlReaderSettings(LoadOptions o) {
            XmlReaderSettings rs = new XmlReaderSettings();
            if ((o & LoadOptions.PreserveWhitespace) == 0) rs.IgnoreWhitespace = true; 
            rs.ProhibitDtd = false;
            rs.MaxCharactersFromEntities = (long)1e7; 
            rs.XmlResolver = null; 
            return rs;
        } 

        internal static XmlWriterSettings GetXmlWriterSettings(SaveOptions o) {
            XmlWriterSettings ws = new XmlWriterSettings();
            if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true; 
            return ws;
        } 
 
        string GetXmlString(SaveOptions o) {
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) { 
                XmlWriterSettings ws = new XmlWriterSettings();
                ws.OmitXmlDeclaration = true;
                if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true;
                if (this is XText) ws.ConformanceLevel = ConformanceLevel.Fragment; 
                using (XmlWriter w = XmlWriter.Create(sw, ws)) {
                    XDocument n = this as XDocument; 
                    if (n != null) { 
                        n.WriteContentTo(w);
                    } 
                    else {
                        WriteTo(w);
                    }
                } 
                return sw.ToString();
            } 
        } 
    }
 
    /// 
    /// Contains functionality to compare nodes for their document order.
    /// This class cannot be inherited.
    ///  
    public sealed class XNodeDocumentOrderComparer: IComparer, IComparer
    { 
        ///  
        /// Compares two nodes to determine their relative XML document order.
        ///  
        /// The first node to compare.
        /// The second node to compare.
        /// 
        /// 0 if the nodes are equal; 
        /// -1 if x is before y;
        /// 1 if x is after y. 
        ///  
        /// 
        /// Thrown if the two nodes do not share a common ancestor. 
        /// 
        public int Compare(XNode x, XNode y) {
            return XNode.CompareDocumentOrder(x, y);
        } 

        ///  
        /// Compares two nodes to determine their relative XML document order. 
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// 
        /// 0 if the nodes are equal;
        /// -1 if x is before y; 
        /// 1 if x is after y.
        ///  
        ///  
        /// Thrown if the two nodes do not share a common ancestor.
        ///  
        /// 
        /// Thrown if either of the two nodes are not derived from XNode.
        /// 
        int IComparer.Compare(object x, object y) { 
            XNode n1 = x as XNode;
            if (n1 == null && x != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "x"); 
            XNode n2 = y as XNode; 
            if (n2 == null && y != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "y");
            return Compare(n1, n2); 
        }
    }

    ///  
    /// Contains functionality to compare nodes for value equality.
    /// This class cannot be inherited. 
    ///  
    public sealed class XNodeEqualityComparer: IEqualityComparer, IEqualityComparer
    { 
        /// 
        /// Compares the values of two nodes.
        /// 
        /// The first node to compare. 
        /// The second node to compare.
        /// true if the nodes are equal, false otherwise. 
        ///  
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two s of different types are never equal. Two 
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of pairwise equal content nodes. 
        /// Two s are equal if their root nodes are equal. Two
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same 
        /// target and data. Two  nodes are equal if the have the
        /// same name, public id, system id, and internal subset. 
        /// 
        public bool Equals(XNode x, XNode y) {
            return XNode.DeepEquals(x, y);
        } 

        ///  
        /// Returns a hash code based on an  objects value. 
        /// 
        /// The node to hash. 
        /// A value-based hash code for the node.
        /// 
        /// The  class's implementation of 
        /// is based on the referential identity of the node. This method computes a 
        /// hash code based on the value of the node.
        ///  
        public int GetHashCode(XNode obj) { 
            return obj != null ? obj.GetDeepHashCode() : 0;
        } 

        /// 
        /// Compares the values of two nodes.
        ///  
        /// The first node to compare.
        /// The second node to compare. 
        /// true if the nodes are equal, false otherwise. 
        /// 
        /// A null node is equal to another null node but unequal to a non-null 
        /// node. Two s of different types are never equal. Two
        ///  nodes are equal if they contain the same text. Two
        ///  nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing 
        /// instructions, contain two equal length sequences of pairwise equal content nodes.
        /// Two s are equal if their root nodes are equal. Two 
        ///  nodes are equal if they contain the same comment text. 
        /// Two  nodes are equal if they have the same
        /// target and data. Two  nodes are equal if the have the 
        /// same name, public id, system id, and internal subset.
        /// 
        bool IEqualityComparer.Equals(object x, object y) {
            XNode n1 = x as XNode; 
            if (n1 == null && x != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "x");
            XNode n2 = y as XNode; 
            if (n2 == null && y != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "y"); 
            return Equals(n1, n2);
        } 

        /// 
        /// Returns a hash code based on a node's value.
        ///  
        /// The node to hash.
        /// A value-based hash code for the node. 
        ///  
        /// The  class's implementation of 
        /// is based on the referential identity of the node. This method computes a 
        /// hash code based on the value of the node.
        /// 
        int IEqualityComparer.GetHashCode(object obj) {
            XNode n = obj as XNode; 
            if (n == null && obj != null) throw new ArgumentException(Res.GetString(Res.Argument_MustBeDerivedFrom, typeof(XNode)), "obj");
            return GetHashCode(n); 
        } 
    }
 
    /// 
    /// Represents a text node.
    /// 
    public class XText : XNode 
    {
        internal string text; 
 
        /// 
        /// Initializes a new instance of the XText class. 
        /// 
        /// The string that contains the value of the text node.
        public XText(string value) {
            if (value == null) throw new ArgumentNullException("value"); 
            text = value;
        } 
 
        /// 
        /// Initializes a new instance of the XText class from another XText object. 
        /// 
        /// The text node to copy from.
        public XText(XText other) {
            if (other == null) throw new ArgumentNullException("other"); 
            text = other.text;
        } 
 
        internal XText(XmlReader r) {
            text = r.Value; 
            r.Read();
        }

        ///  
        /// Gets the node type for this node.
        ///  
        ///  
        /// This property will always return XmlNodeType.Text.
        ///  
        public override XmlNodeType NodeType {
            get {
                return XmlNodeType.Text;
            } 
        }
 
        ///  
        /// Gets or sets the value of this node.
        ///  
        public string Value {
            get {
                return text;
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                text = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        }

        ///  
        /// Write this  to the given .
        ///  
        ///  
        /// The  to write this  to.
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            if (parent is XDocument) {
                writer.WriteWhitespace(text); 
            }
            else { 
                writer.WriteString(text); 
            }
        } 

        internal override void AppendText(StringBuilder sb) {
            sb.Append(text);
        } 

        internal override XNode CloneNode() { 
            return new XText(this); 
        }
 
        internal override bool DeepEquals(XNode node) {
            return node != null && NodeType == node.NodeType && text == ((XText)node).text;
        }
 
        internal override int GetDeepHashCode() {
            return text.GetHashCode(); 
        } 
    }
 
    /// 
    /// Represents a text node that contains CDATA.
    /// 
    public class XCData : XText 
    {
        ///  
        /// Initializes a new instance of the XCData class. 
        /// 
        /// The string that contains the value of the XCData node. 
        public XCData(string value) : base(value) { }

        /// 
        /// Initializes a new instance of the XCData class from another XCData object. 
        /// 
        /// Text node to copy from 
        public XCData(XCData other) : base(other) { } 

        internal XCData(XmlReader r) : base(r) { } 

        /// 
        /// Gets the node type for this node.
        ///  
        /// 
        /// This property will always return XmlNodeType.CDATA. 
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.CDATA;
            }
        }
 
        /// 
        /// Write this  to the given . 
        ///  
        /// 
        /// The  to write this  to. 
        /// 
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            writer.WriteCData(text); 
        }
 
        internal override XNode CloneNode() { 
            return new XCData(this);
        } 
    }

    /// 
    /// Represents a node that can contain other nodes. 
    /// 
    ///  
    /// The two classes that derive from  are 
    ///  and .
    ///  
    public abstract class XContainer : XNode
    {
        internal object content;
 
        internal XContainer() { }
 
        internal XContainer(XContainer other) { 
            if (other == null) throw new ArgumentNullException("other");
            if (other.content is string) { 
                this.content = other.content;
            }
            else {
                XNode n = (XNode)other.content; 
                if (n != null) {
                    do { 
                        n = n.next; 
                        AppendNodeSkipNotify(n.CloneNode());
                    } while (n != other.content); 
                }
            }
        }
 
        /// 
        /// Get the first child node of this node. 
        ///  
        public XNode FirstNode {
            get { 
                XNode last = LastNode;
                return last != null ? last.next : null;
            }
        } 

        ///  
        /// Get the last child node of this node. 
        /// 
        public XNode LastNode { 
            get {
                if (content == null) return null;
                XNode n = content as XNode;
                if (n != null) return n; 
                string s = content as string;
                if (s != null) { 
                    if (s.Length == 0) return null; 
                    XText t = new XText(s);
                    t.parent = this; 
                    t.next = t;
                    Interlocked.CompareExchange(ref content, t, s);
                }
                return (XNode)content; 
            }
        } 
 
        /// 
        /// Adds the specified content as a child (or as children) to this XContainer. The 
        /// content can be simple content, a collection of content objects, a parameter list
        /// of content objects, or null.
        /// 
        ///  
        /// Adds the specified content as a child (or children) of this XContainer.
        ///  
        ///  
        /// A content object containing simple content or a collection of content objects
        /// to be added. 
        /// 
        /// 
        /// When adding simple content, a number of types may be passed to this method.
        /// Valid types include: 
        /// 
        /// string 
        /// double 
        /// float
        /// decimal 
        /// bool
        /// DateTime
        /// DateTimeOffset
        /// TimeSpan 
        /// Any type implementing ToString()
        /// Any type implementing IEnumerable 
        /// 
        /// 
        /// When adding complex content, a number of types may be passed to this method. 
        /// 
        /// XObject
        /// XNode
        /// XAttribute 
        /// Any type implementing IEnumerable
        ///  
        /// 
        /// If an object implements IEnumerable, then the collection in the object is enumerated,
        /// and all items in the collection are added. If the collection contains simple content, 
        /// then the simple content in the collection is concatenated and added as a single
        /// string of simple content. If the collection contains complex content, then each item
        /// in the collection is added separately.
        /// 
        /// If content is null, nothing is added. This allows the results of a query to be passed
        /// as content. If the query returns null, no contents are added, and this method does not 
        /// throw a NullReferenceException. 
        ///
        /// Attributes and simple content can't be added to a document. 
        ///
        /// An added attribute must have a unique name within the element to
        /// which it is being added.
        ///  
        public void Add(object content) {
            if (SkipNotify()) { 
                AddContentSkipNotify(content); 
                return;
            } 
            if (content == null) return;
            XNode n = content as XNode;
            if (n != null) {
                AddNode(n); 
                return;
            } 
            string s = content as string; 
            if (s != null) {
                AddString(s); 
                return;
            }
            XAttribute a = content as XAttribute;
            if (a != null) { 
                AddAttribute(a);
                return; 
            } 
            XStreamingElement x = content as XStreamingElement;
            if (x != null) { 
                AddNode(new XElement(x));
                return;
            }
            object[] o = content as object[]; 
            if (o != null) {
                foreach (object obj in o) Add(obj); 
                return; 
            }
            IEnumerable e = content as IEnumerable; 
            if (e != null) {
                foreach (object obj in e) Add(obj);
                return;
            } 
            AddString(GetStringValue(content));
        } 
 
        /// 
        /// Adds the specified content as a child (or children) of this XContainer. 
        /// 
        /// 
        /// A parameter list of content objects.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void Add(params object[] content) { 
            Add((object)content);
        }

        ///  
        /// Adds the specified content as the first child (or children) of this document or element. The
        /// content can be simple content, a collection of content objects, a parameter 
        /// list of content objects, or null. 
        /// 
        ///  
        /// Adds the specified content as the first child (or children) of this document or element.
        /// 
        /// 
        /// A content object containing simple content or a collection of content objects 
        /// to be added.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void AddFirst(object content) {
            new Inserter(this, null).Add(content);
        } 

        ///  
        /// Adds the specified content as the first children of this document or element. 
        /// 
        ///  
        /// A parameter list of content objects.
        /// 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        ///  
        /// Thrown if the parent is null.
        ///  
        public void AddFirst(params object[] content) {
            AddFirst((object)content);
        }
 
        /// 
        /// Creates an  used to add either nodes 
        /// or attributes to the . The later option 
        /// applies only for .
        ///  
        /// An 
        public XmlWriter CreateWriter() {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.ConformanceLevel = this is XDocument ? ConformanceLevel.Document : ConformanceLevel.Fragment; 
            return XmlWriter.Create(new XNodeBuilder(this), settings);
        } 
 
        /// 
        /// Get descendant elements plus leaf nodes contained in an  
        /// 
        /// IEnumerable over all descendants
        public IEnumerable DescendantNodes() {
            return GetDescendantNodes(false); 
        }
 
        ///  
        /// Returns the descendant s of this .  Note this method will
        /// not return itself in the resulting IEnumerable.  See  if you 
        /// need to include the current  in the results.
        /// 
        /// 
        ///  
        /// An IEnumerable of  with all of the descendants below this  in the XML tree.
        ///  
        public IEnumerable Descendants() { 
            return GetDescendants(null, false);
        } 

        /// 
        /// Returns the Descendant s with the passed in  as an IEnumerable
        /// of XElement. 
        /// 
        /// The  to match against descendant s. 
        /// An  of  
        public IEnumerable Descendants(XName name) {
            return name != null ? GetDescendants(name, false) : XElement.EmptySequence; 
        }

        /// 
        /// Returns the child element with this  or null if there is no child element 
        /// with a matching .
        ///  
        ///  
        /// 
        /// The  to match against this s child elements. 
        /// 
        /// 
        /// An  child that matches the  passed in, or null.
        ///  
        public XElement Element(XName name) {
            XNode n = content as XNode; 
            if (n != null) { 
                do {
                    n = n.next; 
                    XElement e = n as XElement;
                    if (e != null && e.name == name) return e;
                } while (n != content);
            } 
            return null;
        } 
 
        ///
        /// Returns the child s of this . 
        /// 
        /// 
        /// Returns all of the child elements of this .
        ///  
        /// 
        /// An  over all of this 's child s. 
        ///  
        public IEnumerable Elements() {
            return GetElements(null); 
        }

        /// 
        /// Returns the child elements of this  that match the  passed in. 
        /// 
        ///  
        /// The  to match against the  children of this . 
        /// 
        ///  
        /// An  of  children of this  that have
        /// a matching .
        /// 
        public IEnumerable Elements(XName name) { 
            return name != null ? GetElements(name) : XElement.EmptySequence;
        } 
 
        ///
        /// Returns the content of this .  Note that the content does not 
        /// include s.
        /// 
        /// 
        ///  
        /// Returns the content of this  as an  of .  Note
        /// that the content does not include s. 
        ///  
        /// 
        /// The contents of this  
        public IEnumerable Nodes() {
            XNode n = LastNode;
            if (n != null) {
                do { 
                    n = n.next;
                    yield return n; 
                } while (n.parent == this && n != content); 
            }
        } 

        /// 
        /// Removes the nodes from this .  Note this
        /// methods does not remove attributes.  See . 
        /// 
        ///  
        public void RemoveNodes() { 
            if (SkipNotify()) {
                RemoveNodesSkipNotify(); 
                return;
            }
            while (content != null) {
                string s = content as string; 
                if (s != null) {
                    if (s.Length > 0) { 
                        ConvertTextToNode(); 
                    }
                    else { 
                        if (this is XElement) {
                            // Change in the serialization of an empty element:
                            // from start/end tag pair to empty tag
                            NotifyChanging(this, XObjectChangeEventArgs.Value); 
                            if ((object)s != (object)content) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                            content = null; 
                            NotifyChanged(this, XObjectChangeEventArgs.Value); 
                        }
                        else { 
                            content = null;
                        }
                    }
                } 
                XNode last = content as XNode;
                if (last != null) { 
                    XNode n = last.next; 
                    NotifyChanging(n, XObjectChangeEventArgs.Remove);
                    if (last != content || n != last.next) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
                    if (n != last) {
                        last.next = n.next;
                    }
                    else { 
                        content = null;
                    } 
                    n.parent = null; 
                    n.next = null;
                    NotifyChanged(n, XObjectChangeEventArgs.Remove); 
                }
            }
        }
 
        /// 
        /// Replaces the children nodes of this document or element with the specified content. The 
        /// content can be simple content, a collection of content objects, a parameter 
        /// list of content objects, or null.
        ///  
        /// 
        /// Replaces the children nodes of this document or element with the specified content.
        /// 
        ///  
        /// A content object containing simple content or a collection of content objects
        /// that replace the children nodes. 
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        /// 
        public void ReplaceNodes(object content) {
            content = GetContentSnapshot(content); 
            RemoveNodes();
            Add(content); 
        } 

        ///  
        /// Replaces the children nodes of this document or element with the specified content.
        /// 
        /// 
        /// A parameter list of content objects. 
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        public void ReplaceNodes(params object[] content) {
            ReplaceNodes((object)content);
        }
 
        internal virtual void AddAttribute(XAttribute a) {
        } 
 
        internal virtual void AddAttributeSkipNotify(XAttribute a) {
        } 

        internal void AddContentSkipNotify(object content) {
            if (content == null) return;
            XNode n = content as XNode; 
            if (n != null) {
                AddNodeSkipNotify(n); 
                return; 
            }
            string s = content as string; 
            if (s != null) {
                AddStringSkipNotify(s);
                return;
            } 
            XAttribute a = content as XAttribute;
            if (a != null) { 
                AddAttributeSkipNotify(a); 
                return;
            } 
            XStreamingElement x = content as XStreamingElement;
            if (x != null) {
                AddNodeSkipNotify(new XElement(x));
                return; 
            }
            object[] o = content as object[]; 
            if (o != null) { 
                foreach (object obj in o) AddContentSkipNotify(obj);
                return; 
            }
            IEnumerable e = content as IEnumerable;
            if (e != null) {
                foreach (object obj in e) AddContentSkipNotify(obj); 
                return;
            } 
            AddStringSkipNotify(GetStringValue(content)); 
        }
 
        internal void AddNode(XNode n) {
            ValidateNode(n, this);
            if (n.parent != null) {
                n = n.CloneNode(); 
            }
            else { 
                XNode p = this; 
                while (p.parent != null) p = p.parent;
                if (n == p) n = n.CloneNode(); 
            }
            ConvertTextToNode();
            AppendNode(n);
        } 

        internal void AddNodeSkipNotify(XNode n) { 
            ValidateNode(n, this); 
            if (n.parent != null) {
                n = n.CloneNode(); 
            }
            else {
                XNode p = this;
                while (p.parent != null) p = p.parent; 
                if (n == p) n = n.CloneNode();
            } 
            ConvertTextToNode(); 
            AppendNodeSkipNotify(n);
        } 

        internal void AddString(string s) {
            ValidateString(s);
            if (content == null) { 
                if (s.Length > 0) {
                    AppendNode(new XText(s)); 
                } 
                else {
                    if (this is XElement) { 
                        // Change in the serialization of an empty element:
                        // from empty tag to start/end tag pair
                        NotifyChanging(this, XObjectChangeEventArgs.Value);
                        if (content != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
                        content = s;
                        NotifyChanged(this, XObjectChangeEventArgs.Value); 
                    } 
                    else {
                        content = s; 
                    }
                }
            }
            else if (s.Length > 0) { 
                ConvertTextToNode();
                XText tn = content as XText; 
                if (tn != null && !(tn is XCData)) { 
                    tn.Value += s;
                } 
                else {
                    AppendNode(new XText(s));
                }
            } 
        }
 
        internal void AddStringSkipNotify(string s) { 
            ValidateString(s);
            if (content == null) { 
                content = s;
            }
            else if (s.Length > 0) {
                if (content is string) { 
                    content = (string)content + s;
                } 
                else { 
                    XText tn = content as XText;
                    if (tn != null && !(tn is XCData)) { 
                        tn.text += s;
                    }
                    else {
                        AppendNodeSkipNotify(new XText(s)); 
                    }
                } 
            } 
        }
 
        internal void AppendNode(XNode n) {
            bool notify = NotifyChanging(n, XObjectChangeEventArgs.Add);
            if (n.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            AppendNodeSkipNotify(n); 
            if (notify) NotifyChanged(n, XObjectChangeEventArgs.Add);
        } 
 
        internal void AppendNodeSkipNotify(XNode n) {
            n.parent = this; 
            if (content == null || content is string) {
                n.next = n;
            }
            else { 
                XNode x = (XNode)content;
                n.next = x.next; 
                x.next = n; 
            }
            content = n; 
        }

        internal override void AppendText(StringBuilder sb) {
            string s = content as string; 
            if (s != null) {
                sb.Append(s); 
            } 
            else {
                XNode n = (XNode)content; 
                if (n != null) {
                    do {
                        n = n.next;
                        n.AppendText(sb); 
                    } while (n != content);
                } 
            } 
        }
 
        string GetTextOnly() {
            if (content == null) return null;
            string s = content as string;
            if (s == null) { 
                XNode n = (XNode)content;
                do { 
                    n = n.next; 
                    if (n.NodeType != XmlNodeType.Text) return null;
                    s += ((XText)n).Value; 
                } while (n != content);
            }
            return s;
        } 

        string CollectText(ref XNode n) { 
            string s = ""; 
            while (n != null && n.NodeType == XmlNodeType.Text) {
                s += ((XText)n).Value; 
                n = n != content ? n.next : null;
            }
            return s;
        } 

        internal bool ContentsEqual(XContainer e) { 
            if (content == e.content) return true; 
            string s = GetTextOnly();
            if (s != null) return s == e.GetTextOnly(); 
            XNode n1 = content as XNode;
            XNode n2 = e.content as XNode;
            if (n1 != null && n2 != null) {
                n1 = n1.next; 
                n2 = n2.next;
                while (true) { 
                    if (CollectText(ref n1) != e.CollectText(ref n2)) break; 
                    if (n1 == null && n2 == null) return true;
                    if (n1 == null || n2 == null || !n1.DeepEquals(n2)) break; 
                    n1 = n1 != content ? n1.next : null;
                    n2 = n2 != e.content ? n2.next : null;
                }
            } 
            return false;
        } 
 
        internal int ContentsHashCode() {
            string s = GetTextOnly(); 
            if (s != null) return s.GetHashCode();
            int h = 0;
            XNode n = content as XNode;
            if (n != null) { 
                do {
                    n = n.next; 
                    string text = CollectText(ref n); 
                    if (text.Length > 0) {
                        h ^= text.GetHashCode(); 
                    }
                    if (n == null) break;
                    h ^= n.GetDeepHashCode();
                } while (n != content); 
            }
            return h; 
        } 

        internal void ConvertTextToNode() { 
            string s = content as string;
            if (s != null && s.Length > 0) {
                XText t = new XText(s);
                t.parent = this; 
                t.next = t;
                content = t; 
            } 
        }
 
        internal static string GetDateTimeString(DateTime value) {
            return XmlConvert.ToString(value, XmlDateTimeSerializationMode.RoundtripKind);
        }
 
        internal IEnumerable GetDescendantNodes(bool self) {
            if (self) yield return this; 
            XNode n = this; 
            while (true) {
                XContainer c = n as XContainer; 
                XNode first;
                if (c != null && (first = c.FirstNode) != null) {
                    n = first;
                } 
                else {
                    while (n != null && n != this && n == n.parent.content) n = n.parent; 
                    if (n == null || n == this) break; 
                    n = n.next;
                } 
                yield return n;
            }
        }
 
        internal IEnumerable GetDescendants(XName name, bool self) {
            if (self) { 
                XElement e = (XElement)this; 
                if (name == null || e.name == name) yield return e;
            } 
            XNode n = this;
            XContainer c = this;
            while (true) {
                if (c != null && c.content is XNode) { 
                    n = ((XNode)c.content).next;
                } 
                else { 
                    while (n != this && n == n.parent.content) n = n.parent;
                    if (n == this) break; 
                    n = n.next;
                }
                XElement e = n as XElement;
                if (e != null && (name == null || e.name == name)) yield return e; 
                c = e;
            } 
        } 

        IEnumerable GetElements(XName name) { 
            XNode n = content as XNode;
            if (n != null) {
                do {
                    n = n.next; 
                    XElement e = n as XElement;
                    if (e != null && (name == null || e.name == name)) yield return e; 
                } while (n.parent == this && n != content); 
            }
        } 

        internal static string GetStringValue(object value) {
            string s;
            if (value is string) { 
                s = (string)value;
            } 
            else if (value is double) { 
                s = XmlConvert.ToString((double)value);
            } 
            else if (value is float) {
                s = XmlConvert.ToString((float)value);
            }
            else if (value is decimal) { 
                s = XmlConvert.ToString((decimal)value);
            } 
            else if (value is bool) { 
                s = XmlConvert.ToString((bool)value);
            } 
            else if (value is DateTime) {
                s = GetDateTimeString((DateTime)value);
            }
            else if (value is DateTimeOffset) { 
                s = XmlConvert.ToString((DateTimeOffset)value);
            } 
            else if (value is TimeSpan) { 
                s = XmlConvert.ToString((TimeSpan)value);
            } 
            else if (value is XObject) {
                throw new ArgumentException(Res.GetString(Res.Argument_XObjectValue));
            }
            else { 
                s = value.ToString();
            } 
            if (s == null) throw new ArgumentException(Res.GetString(Res.Argument_ConvertToString)); 
            return s;
        } 

        internal void ReadContentFrom(XmlReader r) {
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive));
            XContainer c = this; 
            NamespaceCache eCache = new NamespaceCache();
            NamespaceCache aCache = new NamespaceCache(); 
            do { 
                switch (r.NodeType) {
                    case XmlNodeType.Element: 
                        XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
                        if (r.MoveToFirstAttribute()) {
                            do {
                                e.AppendAttributeSkipNotify(new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value)); 
                            } while (r.MoveToNextAttribute());
                            r.MoveToElement(); 
                        } 
                        c.AddNodeSkipNotify(e);
                        if (!r.IsEmptyElement) { 
                            c = e;
                        }
                        break;
                    case XmlNodeType.EndElement: 
                        if (c.content == null) {
                            c.content = string.Empty; 
                        } 
                        if (c == this) return;
                        c = c.parent; 
                        break;
                    case XmlNodeType.Text:
                    case XmlNodeType.SignificantWhitespace:
                    case XmlNodeType.Whitespace: 
                        c.AddStringSkipNotify(r.Value);
                        break; 
                    case XmlNodeType.CDATA: 
                        c.AddNodeSkipNotify(new XCData(r.Value));
                        break; 
                    case XmlNodeType.Comment:
                        c.AddNodeSkipNotify(new XComment(r.Value));
                        break;
                    case XmlNodeType.ProcessingInstruction: 
                        c.AddNodeSkipNotify(new XProcessingInstruction(r.Name, r.Value));
                        break; 
                    case XmlNodeType.DocumentType: 
                        c.AddNodeSkipNotify(new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value));
                        break; 
                    case XmlNodeType.EntityReference:
                        if (!r.CanResolveEntity) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnresolvedEntityReference));
                        r.ResolveEntity();
                        break; 
                    case XmlNodeType.EndEntity:
                        break; 
                    default: 
                        throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, r.NodeType));
                } 
            } while (r.Read());
        }

        internal void ReadContentFrom(XmlReader r, LoadOptions o) { 
            if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == 0) {
                ReadContentFrom(r); 
                return; 
            }
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive)); 
            XContainer c = this;
            XNode n = null;
            NamespaceCache eCache = new NamespaceCache();
            NamespaceCache aCache = new NamespaceCache(); 
            string baseUri = (o & LoadOptions.SetBaseUri) != 0 ? r.BaseURI : null;
            IXmlLineInfo li = (o & LoadOptions.SetLineInfo) != 0 ? r as IXmlLineInfo : null; 
            do { 
                string uri = r.BaseURI;
                switch (r.NodeType) { 
                    case XmlNodeType.Element:
                        XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
                        if (baseUri != null && baseUri != uri) {
                            e.SetBaseUri(uri); 
                        }
                        if (li != null && li.HasLineInfo()) { 
                            e.SetLineInfo(li.LineNumber, li.LinePosition); 
                        }
                        if (r.MoveToFirstAttribute()) { 
                            do {
                                XAttribute a = new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
                                if (li != null && li.HasLineInfo()) {
                                    a.SetLineInfo(li.LineNumber, li.LinePosition); 
                                }
                                e.AppendAttributeSkipNotify(a); 
                            } while (r.MoveToNextAttribute()); 
                            r.MoveToElement();
                        } 
                        c.AddNodeSkipNotify(e);
                        if (!r.IsEmptyElement) {
                            c = e;
                            if (baseUri != null) { 
                                baseUri = uri;
                            } 
                        } 
                        break;
                    case XmlNodeType.EndElement: 
                        if (c.content == null) {
                            c.content = string.Empty;
                        }
                        if (c == this) return; 
                        if (baseUri != null && c.HasBaseUri) {
                            baseUri = c.parent.BaseUri; 
                        } 
                        c = c.parent;
                        break; 
                    case XmlNodeType.Text:
                    case XmlNodeType.SignificantWhitespace:
                    case XmlNodeType.Whitespace:
                        if ((baseUri != null && baseUri != uri) || 
                            (li != null && li.HasLineInfo())) {
                            n = new XText(r.Value); 
                        } 
                        else {
                            c.AddStringSkipNotify(r.Value); 
                        }
                        break;
                    case XmlNodeType.CDATA:
                        n = new XCData(r.Value); 
                        break;
                    case XmlNodeType.Comment: 
                        n = new XComment(r.Value); 
                        break;
                    case XmlNodeType.ProcessingInstruction: 
                        n = new XProcessingInstruction(r.Name, r.Value);
                        break;
                    case XmlNodeType.DocumentType:
                        n = new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value); 
                        break;
                    case XmlNodeType.EntityReference: 
                        if (!r.CanResolveEntity) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnresolvedEntityReference)); 
                        r.ResolveEntity();
                        break; 
                    case XmlNodeType.EndEntity:
                        break;
                    default:
                        throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_UnexpectedNodeType, r.NodeType)); 
                }
                if (n != null) { 
                    if (baseUri != null && baseUri != uri) { 
                        n.SetBaseUri(uri);
                    } 
                    if (li != null && li.HasLineInfo()) {
                        n.SetLineInfo(li.LineNumber, li.LinePosition);
                    }
                    c.AddNodeSkipNotify(n); 
                    n = null;
                } 
            } while (r.Read()); 
        }
 
        internal void RemoveNode(XNode n) {
            bool notify = NotifyChanging(n, XObjectChangeEventArgs.Remove);
            if (n.parent != this) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            XNode p = (XNode)content; 
            while (p.next != n) p = p.next;
            if (p == n) { 
                content = null; 
            }
            else { 
                if (content == n) content = p;
                p.next = n.next;
            }
            n.parent = null; 
            n.next = null;
            if (notify) NotifyChanged(n, XObjectChangeEventArgs.Remove); 
        } 

        void RemoveNodesSkipNotify() { 
            XNode n = content as XNode;
            if (n != null) {
                do {
                    XNode next = n.next; 
                    n.parent = null;
                    n.next = null; 
                    n = next; 
                } while (n != content);
            } 
            content = null;
        }

        // Validate insertion of the given node. previous is the node after which insertion 
        // will occur. previous == null means at beginning, previous == this means at end.
        internal virtual void ValidateNode(XNode node, XNode previous) { 
        } 

        internal virtual void ValidateString(string s) { 
        }

        internal void WriteContentTo(XmlWriter writer) {
            if (content != null) { 
                if (content is string) {
                    if (this is XDocument) { 
                        writer.WriteWhitespace((string)content); 
                    }
                    else { 
                        writer.WriteString((string)content);
                    }
                }
                else { 
                    XNode n = (XNode)content;
                    do { 
                        n = n.next; 
                        n.WriteTo(writer);
                    } while (n != content); 
                }
            }
        }
 
        static void AddContentToList(List list, object content) {
            IEnumerable e = content is string ? null : content as IEnumerable; 
            if (e == null) { 
                list.Add(content);
            } 
            else {
                foreach (object obj in e) {
                    if (obj != null) AddContentToList(list, obj);
                } 
            }
        } 
 
        static internal object GetContentSnapshot(object content) {
            if (content is string || !(content is IEnumerable)) return content; 
            List list = new List();
            AddContentToList(list, content);
            return list;
        } 
    }
 
    internal struct Inserter 
    {
        XContainer parent; 
        XNode previous;
        string text;

        public Inserter(XContainer parent, XNode anchor) { 
            this.parent = parent;
            this.previous = anchor; 
            this.text = null; 
        }
 
        public void Add(object content) {
            AddContent(content);
            if (text != null) {
                if (parent.content == null) { 
                    if (parent.SkipNotify()) {
                        parent.content = text; 
                    } 
                    else {
                        if (text.Length > 0) { 
                            InsertNode(new XText(text));
                        }
                        else {
                            if (parent is XElement) { 
                                // Change in the serialization of an empty element:
                                // from empty tag to start/end tag pair 
                                parent.NotifyChanging(parent, XObjectChangeEventArgs.Value); 
                                if (parent.content != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                                parent.content = text; 
                                parent.NotifyChanged(parent, XObjectChangeEventArgs.Value);
                            }
                            else {
                                parent.content = text; 
                            }
                        } 
                    } 
                }
                else if (text.Length > 0) { 
                    if (previous is XText && !(previous is XCData)) {
                        ((XText)previous).Value += text;
                    }
                    else { 
                        parent.ConvertTextToNode();
                        InsertNode(new XText(text)); 
                    } 
                }
            } 
        }

        void AddContent(object content) {
            if (content == null) return; 
            XNode n = content as XNode;
            if (n != null) { 
                AddNode(n); 
                return;
            } 
            string s = content as string;
            if (s != null) {
                AddString(s);
                return; 
            }
            XStreamingElement x = content as XStreamingElement; 
            if (x != null) { 
                AddNode(new XElement(x));
                return; 
            }
            object[] o = content as object[];
            if (o != null) {
                foreach (object obj in o) AddContent(obj); 
                return;
            } 
            IEnumerable e = content as IEnumerable; 
            if (e != null) {
                foreach (object obj in e) AddContent(obj); 
                return;
            }
            if (content is XAttribute) throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
            AddString(XContainer.GetStringValue(content)); 
        }
 
        void AddNode(XNode n) { 
            parent.ValidateNode(n, previous);
            if (n.parent != null) { 
                n = n.CloneNode();
            }
            else {
                XNode p = parent; 
                while (p.parent != null) p = p.parent;
                if (n == p) n = n.CloneNode(); 
            } 
            parent.ConvertTextToNode();
            if (text != null) { 
                if (text.Length > 0) {
                    if (previous is XText && !(previous is XCData)) {
                        ((XText)previous).Value += text;
                    } 
                    else {
                        InsertNode(new XText(text)); 
                    } 
                }
                text = null; 
            }
            InsertNode(n);
        }
 
        void AddString(string s) {
            parent.ValidateString(s); 
            text += s; 
        }
 
        // Prepends if previous == null, otherwise inserts after previous
        void InsertNode(XNode n) {
            bool notify = parent.NotifyChanging(n, XObjectChangeEventArgs.Add);
            if (n.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode)); 
            n.parent = parent;
            if (parent.content == null || parent.content is string) { 
                n.next = n; 
                parent.content = n;
            } 
            else if (previous == null) {
                XNode last = (XNode)parent.content;
                n.next = last.next;
                last.next = n; 
            }
            else { 
                n.next = previous.next; 
                previous.next = n;
                if (parent.content == previous) parent.content = n; 
            }
            previous = n;
            if (notify) parent.NotifyChanged(n, XObjectChangeEventArgs.Add);
        } 
    }
 
    internal struct NamespaceCache 
    {
        XNamespace ns; 
        string namespaceName;

        public XNamespace Get(string namespaceName) {
            if ((object)namespaceName == (object)this.namespaceName) return this.ns; 
            this.namespaceName = namespaceName;
            this.ns = XNamespace.Get(namespaceName); 
            return this.ns; 
        }
    } 

    /// 
    /// Represents an XML element.
    ///  
    /// 
    /// An element has an , optionally one or more attributes, 
    /// and can optionally contain content (see . 
    /// An  can contain the following types of content:
    ///    
    ///     string (Text content)
    ///     
    ///     
    ///      
    ///   
    ///  
    [XmlSchemaProvider(null, IsAny=true)] 
    [System.ComponentModel.TypeDescriptionProvider(typeof(ComponentModel.XTypeDescriptionProvider))]
    public class XElement : XContainer, IXmlSerializable 
    {
        static IEnumerable emptySequence;

        ///  
        /// Gets an empty collection of elements.
        ///  
        public static IEnumerable EmptySequence { 
            get {
                if (emptySequence == null) emptySequence = new XElement[0]; 
                return emptySequence;
            }
        }
 
        internal XName name;
        internal XAttribute lastAttr; 
 
        /// 
        /// Initializes a new instance of the XElement class with the specified name. 
        /// 
        /// 
        /// The name of the element.
        ///  
        public XElement(XName name) {
            if (name == null) throw new ArgumentNullException("name"); 
            this.name = name; 
        }
 
        /// 
        /// Initializes a new instance of the XElement class with the specified name and content.
        /// 
        ///  
        /// The element name.
        ///  
        /// The initial contents of the element. 
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        /// 
        public XElement(XName name, object content) : this(name) {
            AddContentSkipNotify(content); 
        }
 
        ///  
        /// Initializes a new instance of the XElement class with the specified name and content.
        ///  
        /// 
        /// The element name.
        /// 
        ///  
        /// The initial content of the element.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public XElement(XName name, params object[] content) : this(name, (object)content) { }

        ///  
        /// Initializes a new instance of the XElement class from another XElement object.
        ///  
        ///  
        /// Another element that will be copied to this element.
        ///  
        /// 
        /// This constructor makes a deep copy from one element to another.
        /// 
        public XElement(XElement other) : base(other) { 
            this.name = other.name;
            XAttribute a = other.lastAttr; 
            if (a != null) { 
                do {
                    a = a.next; 
                    AppendAttributeSkipNotify(new XAttribute(a));
                } while (a != other.lastAttr);
            }
        } 

        ///  
        /// Initializes an XElement object from an  object. 
        /// 
        ///  
        /// The  object whose value will be used
        /// to initialise the new element.
        /// 
        public XElement(XStreamingElement other) { 
            if (other == null) throw new ArgumentNullException("other");
            name = other.name; 
            AddContentSkipNotify(other.content); 
        }
 
        internal XElement() : this("default") {
        }

        internal XElement(XmlReader r) : this(r, LoadOptions.None) { 
        }
 
        internal XElement(XmlReader r, LoadOptions o) { 
            ReadElementFrom(r, o);
        } 

        /// 
        /// Gets the first attribute of an element.
        ///  
        public XAttribute FirstAttribute {
            get { return lastAttr != null ? lastAttr.next : null; } 
        } 

        ///  
        /// Gets a value indicating whether the element as at least one attribute.
        /// 
        public bool HasAttributes {
            get { return lastAttr != null; } 
        }
 
        ///  
        /// Gets a value indicating whether the element has at least one child element.
        ///  
        public bool HasElements {
            get {
                XNode n = content as XNode;
                if (n != null) { 
                    do {
                        if (n is XElement) return true; 
                        n = n.next; 
                    } while (n != content);
                } 
                return false;
            }
        }
 
        /// 
        /// Gets a value indicating whether the element contains no content. 
        ///  
        public bool IsEmpty {
            get { return content == null; } 
        }

        /// 
        /// Gets the last attribute of an element. 
        /// 
        public XAttribute LastAttribute { 
            get { return lastAttr; } 
        }
 
        /// 
        /// Gets the name of this element.
        /// 
        public XName Name { 
            get {
                return name; 
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                name = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name);
            } 
        }
 
        ///  
        /// Gets the node type for this node.
        ///  
        /// 
        /// This property will always return XmlNodeType.Text.
        /// 
        public override XmlNodeType NodeType { 
            get {
                return XmlNodeType.Element; 
            } 
        }
 
        /// 
        /// Gets the text contents of this element.
        /// 
        ///  
        /// If there is text content interspersed with nodes (mixed content) then the text content
        /// will be concatenated and returned. 
        ///  
        public string Value {
            get { 
                if (content == null) return string.Empty;
                string s = content as string;
                if (s != null) return s;
                StringBuilder sb = new StringBuilder(); 
                AppendText(sb);
                return sb.ToString(); 
            } 
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                RemoveNodes();
                Add(value);
            }
        } 

        ///  
        /// Returns this  and all of it's ancestors up 
        /// to the root node.  Optionally an  can be passed
        /// in to target a specific ancestor(s). 
        /// 
        /// 
        /// 
        /// Returns this  and all of it's ancestors up to 
        /// the root node.
        ///  
        ///  
        /// 
        /// An  of  containing all of 
        /// this 's ancestors up to the root node (including
        /// this .
        /// 
        public IEnumerable AncestorsAndSelf() { 
            return GetAncestors(null, true);
        } 
 
        /// 
        /// Returns the ancestor(s) of this  with the matching 
        /// . If this 's 
        /// matches the  passed in then it will be invluded in the
        /// resulting  or .
        ///  
        /// 
        ///  
        /// The  of the target ancestor. 
        /// 
        ///  
        /// An  of  containing the
        /// ancestors of this  with a matching .
        /// 
        public IEnumerable AncestorsAndSelf(XName name) { 
            return name != null ? GetAncestors(name, true) : XElement.EmptySequence;
        } 
 
        /// 
        /// Returns the  associated with this  that has this 
        /// .
        /// 
        /// 
        /// The  of the  to get. 
        /// 
        ///  
        /// The  with the  passed in.  If there is no  
        /// with this  then null is returned.
        ///  
        public XAttribute Attribute(XName name) {
            XAttribute a = lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    if (a.name == name) return a; 
                } while (a != lastAttr); 
            }
            return null; 
        }

        /// 
        /// Returns the  associated with this .  Optionally 
        /// an  can be given to target a specific (s).
        ///  
        ///  
        /// Returns all of the s associated with this .
        ///  
        /// 
        /// 
        /// An  of  containing all of the s
        /// associated with this . 
        /// 
        public IEnumerable Attributes() { 
            return GetAttributes(null); 
        }
 
        /// 
        /// Returns the (s) associated with this  that has the passed
        /// in .
        ///  
        /// 
        ///  
        /// The  of the targeted . 
        /// 
        ///  
        /// The (s) with the matching
        /// 
        public IEnumerable Attributes(XName name) {
            return name != null ? GetAttributes(name) : XAttribute.EmptySequence; 
        }
 
        ///  
        /// Get the self and descendant nodes for an 
        ///  
        /// 
        public IEnumerable DescendantNodesAndSelf() {
            return GetDescendantNodes(true);
        } 

        ///  
        /// Returns this  and all of it's descendants.  Overloads allow 
        /// specification of a type of descendant to return, or a specific 
        /// of a descendant  to match. 
        /// 
        /// 
        /// Returns this  and all of it's descendant s
        /// as an  of . 
        /// 
        ///  
        ///  
        /// An  of  containing this 
        /// and all of it's descendants. 
        /// 
        public IEnumerable DescendantsAndSelf() {
            return GetDescendants(null, true);
        } 

        ///  
        /// Returns the descendants of this  that have a matching  
        /// to the one passed in, including, potentially, this .
        ///  
        /// 
        /// 
        /// The  of the descendant  that is being targeted.
        ///  
        /// 
        /// An  of  containing all of the descendant 
        /// s that have this . 
        /// 
        public IEnumerable DescendantsAndSelf(XName name) { 
            return name != null ? GetDescendants(name, true) : XElement.EmptySequence;
        }

        ///  
        /// Returns the default  of an 
        ///  
        public XNamespace GetDefaultNamespace() { 
            string namespaceName = GetNamespaceOfPrefixInScope("xmlns", null);
            return namespaceName != null ? XNamespace.Get(namespaceName) : XNamespace.None; 
        }

        /// 
        /// Get the namespace associated with a particular prefix for this  
        /// in its document context.
        ///  
        /// The namespace prefix to look up 
        /// An  for the namespace bound to the prefix
        public XNamespace GetNamespaceOfPrefix(string prefix) { 
            if (prefix == null) throw new ArgumentNullException("prefix");
            if (prefix.Length == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidPrefix, prefix));
            if (prefix == "xmlns") return XNamespace.Xmlns;
            string namespaceName = GetNamespaceOfPrefixInScope(prefix, null); 
            if (namespaceName != null) return XNamespace.Get(namespaceName);
            if (prefix == "xml") return XNamespace.Xml; 
            return null; 
        }
 
        /// 
        /// Get the prefix associated with a namespace for an element in its context.
        /// 
        /// The  for which to get a prefix 
        /// The namespace prefix string
        public string GetPrefixOfNamespace(XNamespace ns) { 
            if (ns == null) throw new ArgumentNullException("ns"); 
            string namespaceName = ns.NamespaceName;
            bool hasInScopeNamespace = false; 
            XElement e = this;
            do {
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    bool hasLocalNamespace = false;
                    do { 
                        a = a.next; 
                        if (a.IsNamespaceDeclaration) {
                            if (a.Value == namespaceName) { 
                                if (a.Name.NamespaceName.Length != 0 &&
                                    (!hasInScopeNamespace ||
                                     GetNamespaceOfPrefixInScope(a.Name.LocalName, e) == null)) {
                                    return a.Name.LocalName; 
                                }
                            } 
                            hasLocalNamespace = true; 
                        }
                    } 
                    while (a != e.lastAttr);
                    hasInScopeNamespace |= hasLocalNamespace;
                }
                e = e.parent as XElement; 
            }
            while (e != null); 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) { 
                if (!hasInScopeNamespace || GetNamespaceOfPrefixInScope("xml", null) == null) return "xml";
            } 
            else if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) {
                return "xmlns";
            }
            return null; 
        }
 
        ///  
        /// The Load method provides multiple strategies for creating a new
        ///  and initializing it from a data source containing 
        /// raw XML.  Load from a file (passing in a URI to the file), an
        /// , a , or an
        /// .  Note:  Use 
        /// to create an  from a string containing XML. 
        /// 
        ///  
        ///  
        /// 
        /// Create a new  based on the contents of the file 
        /// referenced by the URI parameter passed in.  Note: Use
        ///  to create an  from
        /// a string containing XML.
        ///  
        /// 
        ///  
        ///  
        /// 
        /// This method uses the  constructor to create 
        /// an  to read the raw XML into the underlying
        /// XML tree.
        /// 
        ///  
        /// A URI string referencing the file to load into a new .
        ///  
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed in uri parameter. 
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Back-compat with System.Xml.")]
        public static XElement Load(string uri) {
            return Load(uri, LoadOptions.None); 
        }
 
        ///  
        /// Create a new  based on the contents of the file
        /// referenced by the URI parameter passed in.  Optionally, whitespace can be preserved. 
        /// 
        /// 
        /// 
        ///  
        /// This method uses the  constructor to create
        /// an  to read the raw XML into an underlying 
        /// XML tree. If LoadOptions.PreserveWhitespace is enabled then 
        /// the  property 
        /// is set to . 
        /// 
        /// 
        /// A string representing the URI of the file to be loaded into a new .
        ///  
        /// 
        /// A set of . 
        ///  
        /// 
        /// An  initialized with the contents of the file referenced 
        /// in the passed uri parameter.  If LoadOptions.PreserveWhitespace is enabled then
        /// significant whitespace will be preserved.
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Back-compat with System.Xml.")] 
        public static XElement Load(string uri, LoadOptions options) {
            XmlReaderSettings rs = GetXmlReaderSettings(options); 
            using (XmlReader r = XmlReader.Create(uri, rs)) { 
                return Load(r, options);
            } 
        }

        /// 
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.
        ///  
        ///  
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        /// 
        /// A new  containing the contents of the passed in
        /// . 
        /// 
        public static XElement Load(TextReader textReader) { 
            return Load(textReader, LoadOptions.None); 
        }
 
        /// 
        /// Create a new  and initialize its underlying XML tree using
        /// the passed  parameter.  Optionally whitespace handling
        /// can be preserved. 
        /// 
        ///  
        /// If LoadOptions.PreserveWhitespace is enabled then 
        /// the  property 
        /// is set to . 
        /// 
        /// 
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        ///  
        /// A set of . 
        /// 
        ///  
        /// A new  containing the contents of the passed in
        /// .
        /// 
        public static XElement Load(TextReader textReader, LoadOptions options) { 
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(textReader, rs)) { 
                return Load(r, options); 
            }
        } 

        /// 
        /// Create a new  containing the contents of the
        /// passed in . 
        /// 
        ///  
        /// An  containing the XML to be read into the new 
        /// .
        ///  
        /// 
        /// A new  containing the contents of the passed
        /// in .
        ///  
        public static XElement Load(XmlReader reader) {
            return Load(reader, LoadOptions.None); 
        } 

        ///  
        /// Create a new  containing the contents of the
        /// passed in .
        /// 
        ///  
        /// An  containing the XML to be read into the new
        /// . 
        ///  
        /// 
        /// A set of . 
        /// 
        /// 
        /// A new  containing the contents of the passed
        /// in . 
        /// 
        public static XElement Load(XmlReader reader, LoadOptions options) { 
            if (reader == null) throw new ArgumentNullException("reader"); 
            if (reader.MoveToContent() != XmlNodeType.Element) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedNodeType, XmlNodeType.Element, reader.NodeType));
            XElement e = new XElement(reader, options); 
            reader.MoveToContent();
            if (!reader.EOF) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedEndOfFile));
            return e;
        } 

        ///  
        /// Parses a string containing XML into an .  Optionally 
        /// whitespace can be preserved.
        ///  
        /// 
        /// Parses a string containing XML into an .
        /// 
        ///  
        /// The XML must contain only one root node.
        ///  
        ///  
        /// A string containing the XML to parse into an .
        ///  
        /// 
        /// An  created from the XML string passed in.
        /// 
        public static XElement Parse(string text) { 
            return Parse(text, LoadOptions.None);
        } 
 
        /// 
        /// Parses a string containing XML into an  and 
        /// optionally preserves the Whitepspace.  See .
        /// 
        /// 
        ///  
        /// 
        /// The XML must contain only one root node. 
        ///  
        /// If LoadOptions.PreserveWhitespace is enabled the underlying
        /// 's 
        /// whitespace handling to significant (see .
        /// 
        /// 
        ///  
        /// 
        /// A string containing the XML to parse into an . 
        ///  
        /// 
        /// A set of . 
        /// 
        /// 
        /// An  created from the XML string passed in.
        ///  
        public static XElement Parse(string text, LoadOptions options) {
            using (StringReader sr = new StringReader(text)) { 
                XmlReaderSettings rs = GetXmlReaderSettings(options); 
                using (XmlReader r = XmlReader.Create(sr, rs)) {
                    return Load(r, options); 
                }
            }
        }
 
        /// 
        /// Removes content and attributes from this . 
        ///  
        /// 
        ///  
        public void RemoveAll() {
            RemoveAttributes();
            RemoveNodes();
        } 

        ///  
        /// Removes that attributes of this . 
        /// 
        ///  
        /// 
        public void RemoveAttributes() {
            if (SkipNotify()) {
                RemoveAttributesSkipNotify(); 
                return;
            } 
            while (lastAttr != null) { 
                XAttribute a = lastAttr.next;
                NotifyChanging(a, XObjectChangeEventArgs.Remove); 
                if (lastAttr == null || a != lastAttr.next) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
                if (a != lastAttr) {
                    lastAttr.next = a.next;
                } 
                else {
                    lastAttr = null; 
                } 
                a.parent = null;
                a.next = null; 
                NotifyChanged(a, XObjectChangeEventArgs.Remove);
            }
        }
 
        /// 
        /// Replaces the child nodes and the attributes of this element with the 
        /// specified content. The content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, or null.
        ///  
        /// 
        /// Replaces the children nodes and the attributes of this element with the specified content.
        /// 
        ///  
        /// The content that will replace the child nodes and attributes of this element.
        ///  
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public void ReplaceAll(object content) {
            content = GetContentSnapshot(content);
            RemoveAll(); 
            Add(content);
        } 
 
        /// 
        /// Replaces the children nodes and the attributes of this element with the specified content. 
        /// 
        /// 
        /// A parameter list of content objects.
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method. 
        /// 
        public void ReplaceAll(params object[] content) { 
            ReplaceAll((object)content);
        }

        ///  
        /// Replaces the attributes of this element with the specified content.
        /// The content can be simple content, a collection of 
        /// content objects, a parameter list of content objects, or null. 
        /// 
        ///  
        /// Replaces the attributes of this element with the specified content.
        /// 
        /// 
        /// The content that will replace the attributes of this element. 
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added 
        /// using this method.
        ///  
        public void ReplaceAttributes(object content) {
            content = GetContentSnapshot(content);
            RemoveAttributes();
            Add(content); 
        }
 
        ///  
        /// Replaces the attributes of this element with the specified content.
        ///  
        /// 
        /// A parameter list of content objects.
        /// 
        ///  
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        ///  
        public void ReplaceAttributes(params object[] content) {
            ReplaceAttributes((object)content); 
        }

        ///
        /// Outputs this 's underlying XML tree.  The output can 
        /// be saved to a file, an , a ,
        /// or an .  Optionally whitespace can be preserved. 
        ///  
        /// 
        /// Output this  to a file. 
        /// 
        /// 
        /// The format will be indented by default.  If you want
        /// no indenting then use the SaveOptions version of Save (see 
        /// ) enabling
        /// SaveOptions.DisableFormatting 
        ///  
        /// 
        /// The name of the file to output the XML to. 
        /// 
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None);
        } 

        ///  
        /// Output this  to a file. 
        /// 
        ///  
        /// The name of the file to output the XML to.
        /// 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented. 
        /// 
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = GetXmlWriterSettings(options); 
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) {
                Save(w); 
            }
        }

        ///  
        /// Output this  to the passed in .
        ///  
        ///  
        /// The format will be indented by default.  If you want
        /// no indenting then use the SaveOptions version of Save (see 
        /// ) enabling
        /// SaveOptions.DisableFormatting
        /// 
        ///  
        /// The  to output this  to.
        ///  
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None);
        } 

        /// 
        /// Output this  to a .
        ///  
        /// 
        /// The  to output the XML to. 
        ///  
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented. 
        /// 
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) { 
                Save(w);
            } 
        } 

        ///  
        /// Output this  to an .
        /// 
        /// 
        /// The  to output the XML to. 
        /// 
        public void Save(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteStartDocument();
            WriteTo(writer); 
            writer.WriteEndDocument();
        }

        ///  
        /// Sets the value of an attribute. The value is assigned to the attribute with the given
        /// name. If no attribute with the given name exists, a new attribute is added. If the 
        /// value is null, the attribute with the given name, if any, is deleted. 
        /// 
        ///  
        /// 
        /// 
        /// 
        /// The name of the attribute whose value to change. 
        /// 
        ///  
        /// The value to assign to the attribute. The attribute is deleted if the value is null. 
        /// Otherwise, the value is converted to its string representation and assigned to the
        ///  property of the attribute. 
        /// 
        /// 
        /// Thrown if the value is an instance of .
        ///  
        public void SetAttributeValue(XName name, object value) {
            XAttribute a = Attribute(name); 
            if (value == null) { 
                if (a != null) RemoveAttribute(a);
            } 
            else {
                if (a != null) {
                    a.Value = GetStringValue(value);
                } 
                else {
                    AppendAttribute(new XAttribute(name, value)); 
                } 
            }
        } 

        /// 
        /// Sets the value of a child element. The value is assigned to the first child element
        /// with the given name. If no child element with the given name exists, a new child 
        /// element is added. If the value is null, the first child element with the given name,
        /// if any, is deleted. 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// The name of the child element whose value to change.
        ///  
        /// 
        /// The value to assign to the child element. The child element is deleted if the value 
        /// is null. Otherwise, the value is converted to its string representation and assigned 
        /// to the  property of the child element.
        ///  
        /// 
        /// Thrown if the value is an instance of .
        /// 
        public void SetElementValue(XName name, object value) { 
            XElement e = Element(name);
            if (value == null) { 
                if (e != null) RemoveNode(e); 
            }
            else { 
                if (e != null) {
                    e.Value = GetStringValue(value);
                }
                else { 
                    AddNode(new XElement(name, GetStringValue(value)));
                } 
            } 
        }
 
        /// 
        /// Sets the value of this element.
        /// 
        ///  
        /// 
        ///  
        ///  
        /// The value to assign to this element. The value is converted to its string representation
        /// and assigned to the  property. 
        /// 
        /// 
        /// Thrown if the specified value is null.
        ///  
        public void SetValue(object value) {
            if (value == null) throw new ArgumentNullException("value"); 
            Value = GetStringValue(value); 
        }
 
        /// 
        /// Write this  to the passed in .
        /// 
        ///  
        /// The  to write this  to.
        ///  
        public override void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer");
            new ElementWriter(writer).WriteElement(this); 
        }

        /// 
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// If the  is a subtre (an  
        /// that has  children.  The concatenated string
        /// value of all of the 's text and descendants 
        /// text is returned.
        /// 
        /// 
        /// The  to cast to a string. 
        /// 
        ///  
        /// The content of this  as a . 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator string(XElement element) {
            if (element == null) return null;
            return element.Value; 
        }
 
        ///  
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to .
        /// 
        ///  
        /// The content of this  as a .
        ///  
        ///  
        /// Thrown if the element does not contain a valid boolean value.
        ///  
        /// 
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator bool(XElement element) { 
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToBoolean(element.Value.ToLower(CultureInfo.InvariantCulture));
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        /// 
        /// Thrown if the element does not contain a valid boolean value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator bool?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToBoolean(element.Value.ToLower(CultureInfo.InvariantCulture)); 
        }

        /// 
        /// Cast the value of this  to an . 
        /// 
        ///  
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a .
        /// 
        /// 
        /// Thrown if the element does not contain a valid integer value. 
        /// 
        ///  
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator int(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToInt32(element.Value); 
        }
 
        ///  
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?.
        /// 
        ///  
        /// The content of this  as a ?.
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid integer value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator int?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToInt32(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to an . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid unsigned integer value. 
        /// 
        /// 
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator uint(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToUInt32(element.Value); 
        }

        /// 
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?.
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid unsigned integer value. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator uint?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToUInt32(element.Value);
        }

        ///  
        /// Cast the value of this  to a .
        ///  
        ///  
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a .
        /// 
        ///  
        /// Thrown if the element does not contain a valid long integer value.
        ///  
        ///  
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator long(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToInt64(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid long integer value. 
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator long?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToInt64(element.Value); 
        } 

        ///  
        /// Cast the value of this  to an .
        /// 
        /// 
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a . 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid unsigned long integer value.
        /// 
        /// 
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator ulong(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToUInt64(element.Value);
        }

        ///  
        /// Cast the value of this  to an ?.
        ///  
        ///  
        /// The  to cast to ?.
        ///  
        /// 
        /// The content of this  as a ?.
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid unsigned long integer value.
        ///  
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator ulong?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToUInt64(element.Value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid float value. 
        ///  
        /// 
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator float(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToSingle(element.Value); 
        } 

        ///  
        /// Cast the value of this  to an ?.
        /// 
        /// 
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?. 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid float value.
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator float?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToSingle(element.Value); 
        }
 
        /// 
        /// Cast the value of this  to a .
        /// 
        ///  
        /// The  to cast to .
        ///  
        ///  
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid double value.
        /// 
        ///  
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator double(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToDouble(element.Value);
        }
 
        /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid double value. 
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator double?(XElement element) {
            if (element == null) return null;
            return XmlConvert.ToDouble(element.Value);
        } 

        ///  
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// The  to cast to .
        /// 
        /// 
        /// The content of this  as a . 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid decimal value. 
        /// 
        ///  
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator decimal(XElement element) {
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToDecimal(element.Value); 
        }
 
        /// 
        /// Cast the value of this  to an ?.
        /// 
        ///  
        /// The  to cast to ?.
        ///  
        ///  
        /// The content of this  as a ?.
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid decimal value.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator decimal?(XElement element) { 
            if (element == null) return null; 
            return XmlConvert.ToDecimal(element.Value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        /// 
        /// Thrown if the specified element is null. 
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator DateTime(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return DateTime.Parse(element.Value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 

        ///  
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?.
        /// 
        /// 
        /// The content of this  as a ?. 
        /// 
        ///  
        /// Thrown if the specified element does not contain a valid  value. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator DateTime?(XElement element) {
            if (element == null) return null;
            return DateTime.Parse(element.Value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind); 
        }
 
        ///  
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to .
        /// 
        ///  
        /// The content of this  as a .
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        /// 
        /// Thrown if the specified element is null.
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator DateTimeOffset(XElement element) { 
            if (element == null) throw new ArgumentNullException("element"); 
            return XmlConvert.ToDateTimeOffset(element.Value);
        } 

        /// 
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator DateTimeOffset?(XElement element) { 
            if (element == null) return null;
            return XmlConvert.ToDateTimeOffset(element.Value); 
        }

        /// 
        /// Cast the value of this  to a . 
        /// 
        ///  
        /// The  to cast to . 
        /// 
        ///  
        /// The content of this  as a .
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid  value. 
        /// 
        ///  
        /// Thrown if the specified element is null. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator TimeSpan(XElement element) {
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToTimeSpan(element.Value); 
        }
 
        ///  
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?.
        /// 
        ///  
        /// The content of this  as a ?.
        ///  
        ///  
        /// Thrown if the specified element does not contain a valid  value.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")]
        public static explicit operator TimeSpan?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToTimeSpan(element.Value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified element does not contain a valid guid. 
        /// 
        /// 
        /// Thrown if the specified element is null.
        ///  
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator Guid(XElement element) { 
            if (element == null) throw new ArgumentNullException("element");
            return XmlConvert.ToGuid(element.Value); 
        }

        /// 
        /// Cast the value of this  to an ?. 
        /// 
        ///  
        /// The  to cast to ?. 
        /// 
        ///  
        /// The content of this  as a ?.
        /// 
        /// 
        /// Thrown if the specified element does not contain a valid guid. 
        /// 
        [CLSCompliant(false)] 
        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Operator marked with CLSCompliant(false).")] 
        public static explicit operator Guid?(XElement element) {
            if (element == null) return null; 
            return XmlConvert.ToGuid(element.Value);
        }

        ///  
        /// This method is obsolete for the IXmlSerializable contract.
        ///  
        XmlSchema IXmlSerializable.GetSchema() { 
            return null;
        } 

        /// 
        /// Generates a  from its XML respresentation.
        ///  
        /// 
        /// The  stream from which the  
        /// is deserialized. 
        /// 
        void IXmlSerializable.ReadXml(XmlReader reader) { 
            if (reader == null) throw new ArgumentNullException("reader");
            if (parent != null || annotations != null || content != null || lastAttr != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DeserializeInstance));
            if (reader.MoveToContent() != XmlNodeType.Element) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedNodeType, XmlNodeType.Element, reader.NodeType));
            ReadElementFrom(reader, LoadOptions.None); 
        }
 
        ///  
        /// Converts a  into its XML representation.
        ///  
        /// 
        /// The  stream to which the 
        /// is serialized.
        ///  
        void IXmlSerializable.WriteXml(XmlWriter writer) {
            WriteTo(writer); 
        } 

        internal override void AddAttribute(XAttribute a) { 
            if (Attribute(a.Name) != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DuplicateAttribute));
            if (a.parent != null) a = new XAttribute(a);
            AppendAttribute(a);
        } 

        internal override void AddAttributeSkipNotify(XAttribute a) { 
            if (Attribute(a.Name) != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DuplicateAttribute)); 
            if (a.parent != null) a = new XAttribute(a);
            AppendAttributeSkipNotify(a); 
        }

        internal void AppendAttribute(XAttribute a) {
            bool notify = NotifyChanging(a, XObjectChangeEventArgs.Add); 
            if (a.parent != null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            AppendAttributeSkipNotify(a); 
            if (notify) NotifyChanged(a, XObjectChangeEventArgs.Add); 
        }
 
        internal void AppendAttributeSkipNotify(XAttribute a) {
            a.parent = this;
            if (lastAttr == null) {
                a.next = a; 
            }
            else { 
                a.next = lastAttr.next; 
                lastAttr.next = a;
            } 
            lastAttr = a;
        }

        bool AttributesEqual(XElement e) { 
            XAttribute a1 = lastAttr;
            XAttribute a2 = e.lastAttr; 
            if (a1 != null && a2 != null) { 
                do {
                    a1 = a1.next; 
                    a2 = a2.next;
                    if (a1.name != a2.name || a1.value != a2.value) return false;
                } while (a1 != lastAttr);
                return a2 == e.lastAttr; 
            }
            return a1 == null && a2 == null; 
        } 

        internal override XNode CloneNode() { 
            return new XElement(this);
        }

        internal override bool DeepEquals(XNode node) { 
            XElement e = node as XElement;
            return e != null && name == e.name && ContentsEqual(e) && AttributesEqual(e); 
        } 

        IEnumerable GetAttributes(XName name) { 
            XAttribute a = lastAttr;
            if (a != null) {
                do {
                    a = a.next; 
                    if (name == null || a.name == name) yield return a;
                } while (a.parent == this && a != lastAttr); 
            } 
        }
 
        string GetNamespaceOfPrefixInScope(string prefix, XElement outOfScope) {
            XElement e = this;
            while (e != outOfScope) {
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do { 
                        a = a.next; 
                        if (a.IsNamespaceDeclaration && a.Name.LocalName == prefix) return a.Value;
                    } 
                    while (a != e.lastAttr);
                }
                e = e.parent as XElement;
            } 
            return null;
        } 
 
        internal override int GetDeepHashCode() {
            int h = name.GetHashCode(); 
            h ^= ContentsHashCode();
            XAttribute a = lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    h ^= a.GetDeepHashCode(); 
                } while (a != lastAttr); 
            }
            return h; 
        }

        void ReadElementFrom(XmlReader r, LoadOptions o) {
            if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedInteractive)); 
            name = XNamespace.Get(r.NamespaceURI).GetName(r.LocalName);
            if ((o & LoadOptions.SetBaseUri) != 0) { 
                string baseUri = r.BaseURI; 
                if (baseUri != null && baseUri.Length != 0) {
                    SetBaseUri(baseUri); 
                }
            }
            IXmlLineInfo li = null;
            if ((o & LoadOptions.SetLineInfo) != 0) { 
                li = r as IXmlLineInfo;
                if (li != null && li.HasLineInfo()) { 
                    SetLineInfo(li.LineNumber, li.LinePosition); 
                }
            } 
            if (r.MoveToFirstAttribute()) {
                do {
                    XAttribute a = new XAttribute(XNamespace.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
                    if (li != null && li.HasLineInfo()) { 
                        a.SetLineInfo(li.LineNumber, li.LinePosition);
                    } 
                    AppendAttributeSkipNotify(a); 
                } while (r.MoveToNextAttribute());
                r.MoveToElement(); 
            }
            if (!r.IsEmptyElement) {
                r.Read();
                ReadContentFrom(r, o); 
            }
            r.Read(); 
        } 

        internal void RemoveAttribute(XAttribute a) { 
            bool notify = NotifyChanging(a, XObjectChangeEventArgs.Remove);
            if (a.parent != this) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExternalCode));
            XAttribute p = lastAttr, n;
            while ((n = p.next) != a) p = n; 
            if (p == a) {
                lastAttr = null; 
            } 
            else {
                if (lastAttr == a) lastAttr = p; 
                p.next = a.next;
            }
            a.parent = null;
            a.next = null; 
            if (notify) NotifyChanged(a, XObjectChangeEventArgs.Remove);
        } 
 
        void RemoveAttributesSkipNotify() {
            if (lastAttr != null) { 
                XAttribute a = lastAttr;
                do {
                    XAttribute next = a.next;
                    a.parent = null; 
                    a.next = null;
                    a = next; 
                } while (a != lastAttr); 
                lastAttr = null;
            } 
        }

        internal override void ValidateNode(XNode node, XNode previous) {
            if (node is XDocument) throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.Document)); 
            if (node is XDocumentType) throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.DocumentType));
        } 
    } 

    internal struct ElementWriter 
    {
        XmlWriter writer;
        NamespaceResolver resolver;
 
        public ElementWriter(XmlWriter writer) {
            this.writer = writer; 
            this.resolver = new NamespaceResolver(); 
        }
 
        public void WriteElement(XElement e) {
            PushAncestors(e);
            XElement root = e;
            XNode n = e; 
            while (true) {
                e = n as XElement; 
                if (e != null) { 
                    WriteStartElement(e);
                    if (e.content == null) { 
                        WriteEndElement();
                    }
                    else {
                        string s = e.content as string; 
                        if (s != null) {
                            writer.WriteString(s); 
                            WriteFullEndElement(); 
                        }
                        else { 
                            n = ((XNode)e.content).next;
                            continue;
                        }
                    } 
                }
                else { 
                    n.WriteTo(writer); 
                }
                while (n != root && n == n.parent.content) { 
                    n = n.parent;
                    WriteFullEndElement();

                } 
                if (n == root) break;
                n = n.next; 
            } 
        }
 
        string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) {
            string namespaceName = ns.NamespaceName;
            if (namespaceName.Length == 0) return string.Empty;
            string prefix = resolver.GetPrefixOfNamespace(ns, allowDefaultNamespace); 
            if (prefix != null) return prefix;
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml"; 
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns"; 
            return null;
        } 

        void PushAncestors(XElement e) {
            while (true) {
                e = e.parent as XElement; 
                if (e == null) break;
                XAttribute a = e.lastAttr; 
                if (a != null) { 
                    do {
                        a = a.next; 
                        if (a.IsNamespaceDeclaration) {
                            resolver.AddFirst(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value));
                        }
                    } while (a != e.lastAttr); 
                }
            } 
        } 

        void PushElement(XElement e) { 
            resolver.PushScope();
            XAttribute a = e.lastAttr;
            if (a != null) {
                do { 
                    a = a.next;
                    if (a.IsNamespaceDeclaration) { 
                        resolver.Add(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value)); 
                    }
                } while (a != e.lastAttr); 
            }
        }

        void WriteEndElement() { 
            writer.WriteEndElement();
            resolver.PopScope(); 
        } 

        void WriteFullEndElement() { 
            writer.WriteFullEndElement();
            resolver.PopScope();
        }
 
        void WriteStartElement(XElement e) {
            PushElement(e); 
            XNamespace ns = e.Name.Namespace; 
            writer.WriteStartElement(GetPrefixOfNamespace(ns, true), e.Name.LocalName, ns.NamespaceName);
            XAttribute a = e.lastAttr; 
            if (a != null) {
                do {
                    a = a.next;
                    ns = a.Name.Namespace; 
                    string localName = a.Name.LocalName;
                    string namespaceName = ns.NamespaceName; 
                    writer.WriteAttributeString(GetPrefixOfNamespace(ns, false), localName, namespaceName.Length == 0 && localName == "xmlns" ? XNamespace.xmlnsPrefixNamespace : namespaceName, a.Value); 
                } while (a != e.lastAttr);
            } 
        }
    }

    internal struct NamespaceResolver { 
        class NamespaceDeclaration {
            public string prefix; 
            public XNamespace ns; 
            public int scope;
            public NamespaceDeclaration prev; 
        }

        int scope;
        NamespaceDeclaration declaration; 
        NamespaceDeclaration rover;
 
        public void PushScope() { 
            scope++;
        } 

        public void PopScope() {
            NamespaceDeclaration d = declaration;
            if (d != null) { 
                do {
                    d = d.prev; 
                    if (d.scope != scope) break; 
                    if (d == declaration) {
                        declaration = null; 
                    }
                    else {
                        declaration.prev = d.prev;
                    } 
                    rover = null;
                } while (d != declaration && declaration != null); 
            } 
            scope--;
        } 

        public void Add(string prefix, XNamespace ns) {
            NamespaceDeclaration d = new NamespaceDeclaration();
            d.prefix = prefix; 
            d.ns = ns;
            d.scope = scope; 
            if (declaration == null) { 
                declaration = d;
            } 
            else {
                d.prev = declaration.prev;
            }
            declaration.prev = d; 
            rover = null;
        } 
 
        public void AddFirst(string prefix, XNamespace ns) {
            NamespaceDeclaration d = new NamespaceDeclaration(); 
            d.prefix = prefix;
            d.ns = ns;
            d.scope = scope;
            if (declaration == null) { 
                d.prev = d;
            } 
            else { 
                d.prev = declaration.prev;
                declaration.prev = d; 
            }
            declaration = d;
            rover = null;
        } 

        // Only elements allow default namespace declarations. The rover 
        // caches the last namespace declaration used by an element. 
        public string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) {
            if (rover != null && rover.ns == ns && (allowDefaultNamespace || rover.prefix.Length > 0)) return rover.prefix; 
            NamespaceDeclaration d = declaration;
            if (d != null) {
                do {
                    d = d.prev; 
                    if (d.ns == ns) {
                        NamespaceDeclaration x = declaration.prev; 
                        while (x != d && x.prefix != d.prefix) { 
                            x = x.prev;
                        } 
                        if (x == d) {
                            if (allowDefaultNamespace) {
                                rover = d;
                                return d.prefix; 
                            }
                            else if (d.prefix.Length > 0) { 
                                return d.prefix; 
                            }
                        } 
                    }
                } while (d != declaration);
            }
            return null; 
        }
    } 
 
    /// 
    /// Specifies a set of options for Load(). 
    /// 
    [Flags()]
    public enum LoadOptions {
        /// Default options. 
        None                = 0x00000000,
 
        /// Preserve whitespace. 
        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification="Back-compat with System.Xml.")]
        PreserveWhitespace  = 0x00000001, 

        /// Set the BaseUri property.
        SetBaseUri          = 0x00000002,
 
        /// Set the IXmlLineInfo.
        SetLineInfo         = 0x00000004, 
    } 

    ///  
    /// Specifies a set of options for Save().
    /// 
    [Flags()]
    public enum SaveOptions { 
        /// Default options.
        None                = 0x00000000, 
 
        /// Disable formatting.
        DisableFormatting   = 0x00000001, 
    }

    /// 
    /// Represents an XML document. 
    /// 
    ///  
    /// An  can contain: 
    /// 
    ///    
    ///   A Document Type Declaration (DTD), see 
    ///   
    ///   One root element.
    ///   Zero or more  objects. 
    ///   Zero or more  objects.
    ///  
    ///  
    public class XDocument : XContainer
    { 
        XDeclaration declaration;

        ///
        /// Initializes a new instance of the  class. 
        /// Overloaded constructors are provided for creating a new empty
        /// , creating an  with 
        /// a parameter list of initial content, and as a copy of another 
        ///  object.
        ///  
        /// 
        /// Initializes a new instance of the  class.
        /// 
        public XDocument() { 
        }
 
        ///  
        /// Initializes a new instance of the  class with the specified content.
        ///  
        /// 
        /// A parameter list of content objects to add to this document.
        /// 
        ///  
        /// Valid content includes:
        ///  
        /// Zero or one  objects 
        /// Zero or one elements
        /// Zero or more comments 
        /// Zero or more processing instructions
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method. 
        /// 
        public XDocument(params object[] content) : this() { 
            AddContentSkipNotify(content); 
        }
 
        /// 
        /// Initializes a new instance of the  class
        /// with the specifed  and content.
        ///  
        /// 
        /// The XML declaration for the document. 
        ///  
        /// 
        /// The contents of the document. 
        /// 
        /// 
        /// Valid content includes:
        ///  
        /// Zero or one  objects
        /// Zero or one elements 
        /// Zero or more comments 
        /// Zero or more processing instructions
        ///  
        /// 
        /// See XContainer.Add(object content) for details about the content that can be added
        /// using this method.
        ///  
        public XDocument(XDeclaration declaration, params object[] content) : this(content) {
            this.declaration = declaration; 
        } 

        ///  
        /// Initializes a new instance of the  class from an
        /// existing XDocument object.
        /// 
        ///  
        /// The  object that will be copied.
        ///  
        public XDocument(XDocument other) : base(other) { 
            if (other.declaration != null) {
                declaration = new XDeclaration(other.declaration); 
            }
        }

        ///  
        /// Gets the XML declaration for this document.
        ///  
        public XDeclaration Declaration { 
            get { return declaration; }
            set { declaration = value; } 
        }

        /// 
        /// Gets the Document Type Definition (DTD) for this document. 
        /// 
        public XDocumentType DocumentType { 
            get { 
                return GetFirstNode();
            } 
        }

        /// 
        /// Gets the node type for this node. 
        /// 
        ///  
        /// This property will always return XmlNodeType.Document. 
        /// 
        public override XmlNodeType NodeType { 
            get {
                return XmlNodeType.Document;
            }
        } 

        ///  
        /// Gets the root element of the XML Tree for this document. 
        /// 
        public XElement Root { 
            get {
                return GetFirstNode();
            }
        } 

        ///  
        /// The Load method provides multiple strategies for creating a new 
        ///  and initializing it from a data source containing
        /// raw XML.  Load from a file (passing in a URI to the file), an 
        /// , a , or an
        /// .  Note:  Use 
        /// to create an  from a string containing XML.
        ///  
        /// 
        ///  
        /// Create a new  based on the contents of the file 
        /// referenced by the URI parameter passed in.  Note: Use
        ///  to create an  from 
        /// a string containing XML.
        /// 
        /// 
        ///  
        /// 
        /// This method uses the  constructor to create 
        /// an  to read the raw XML into the underlying 
        /// XML tree.
        ///  
        /// 
        /// A URI string referencing the file to load into a new .
        /// 
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed in uri parameter. 
        ///  
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId="0#", Justification = "Back-compat with System.Xml.")]
        public static XDocument Load(string uri) { 
            return Load(uri, LoadOptions.None);
        }

        ///  
        /// Create a new  based on the contents of the file
        /// referenced by the URI parameter passed in.  Optionally, whitespace can be preserved. 
        ///  
        /// 
        ///  
        /// This method uses the  constructor to create
        /// an  to read the raw XML into an underlying
        /// XML tree.  If LoadOptions.PreserveWhitespace is enabled then
        /// the  property  
        /// is set to .
        ///  
        ///  
        /// A string representing the URI of the file to be loaded into a new .
        ///  
        /// 
        /// A set of .
        /// 
        ///  
        /// An  initialized with the contents of the file referenced
        /// in the passed uri parameter.  If LoadOptions.PreserveWhitespace is enabled then 
        /// significant whitespace will be preserved. 
        /// 
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId="0#", Justification = "Back-compat with System.Xml.")] 
        public static XDocument Load(string uri, LoadOptions options) {
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(uri, rs)) {
                return Load(r, options); 
            }
        } 
 
        /// 
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.
        /// 
        /// 
        /// A  containing the raw XML to read into the newly 
        /// created .
        ///  
        ///  
        /// A new  containing the contents of the passed in
        /// . 
        /// 
        public static XDocument Load(TextReader textReader) {
            return Load(textReader, LoadOptions.None);
        } 

        ///  
        /// Create a new  and initialize its underlying XML tree using 
        /// the passed  parameter.  Optionally whitespace handling
        /// can be preserved. 
        /// 
        /// 
        /// If LoadOptions.PreserveWhitespace is enabled then
        /// the  property  
        /// is set to .
        ///  
        ///  
        /// A  containing the raw XML to read into the newly
        /// created . 
        /// 
        /// 
        /// A set of .
        ///  
        /// 
        /// A new  containing the contents of the passed in 
        /// . 
        /// 
        public static XDocument Load(TextReader textReader, LoadOptions options) { 
            XmlReaderSettings rs = GetXmlReaderSettings(options);
            using (XmlReader r = XmlReader.Create(textReader, rs)) {
                return Load(r, options);
            } 
        }
 
        ///  
        /// Create a new  containing the contents of the
        /// passed in . 
        /// 
        /// 
        /// An  containing the XML to be read into the new
        /// . 
        /// 
        ///  
        /// A new  containing the contents of the passed 
        /// in .
        ///  
        public static XDocument Load(XmlReader reader) {
            return Load(reader, LoadOptions.None);
        }
 
        /// 
        /// Create a new  containing the contents of the 
        /// passed in . 
        /// 
        ///  
        /// An  containing the XML to be read into the new
        /// .
        /// 
        ///  
        /// A set of .
        ///  
        ///  
        /// A new  containing the contents of the passed
        /// in . 
        /// 
        public static XDocument Load(XmlReader reader, LoadOptions options) {
            if (reader == null) throw new ArgumentNullException("reader");
            if (reader.ReadState == ReadState.Initial) reader.Read(); 
            XDocument d = new XDocument();
            if ((options & LoadOptions.SetBaseUri) != 0) { 
                string baseUri = reader.BaseURI; 
                if (baseUri != null && baseUri.Length != 0) {
                    d.SetBaseUri(baseUri); 
                }
            }
            if ((options & LoadOptions.SetLineInfo) != 0) {
                IXmlLineInfo li = reader as IXmlLineInfo; 
                if (li != null && li.HasLineInfo()) {
                    d.SetLineInfo(li.LineNumber, li.LinePosition); 
                } 
            }
            if (reader.NodeType == XmlNodeType.XmlDeclaration) { 
                d.Declaration = new XDeclaration(reader);
            }
            d.ReadContentFrom(reader, options);
            if (!reader.EOF) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_ExpectedEndOfFile)); 
            if (d.Root == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingRoot));
            return d; 
        } 

        ///  
        /// Create a new  from a string containing
        /// XML.  Optionally whitespace can be preserved.
        /// 
        ///  
        /// Create a new  from a string containing
        /// XML. 
        ///  
        /// 
        /// A string containing XML. 
        /// 
        /// 
        /// An  containing an XML tree initialized from the
        /// passed in XML string. 
        /// 
        public static XDocument Parse(string text) { 
            return Parse(text, LoadOptions.None); 
        }
 
        /// 
        /// Create a new  from a string containing
        /// XML.  Optionally whitespace can be preserved.
        ///  
        /// 
        /// This method uses  passing it a StringReader 
        /// constructed from the passed in XML String.  If LoadOptions.PreserveWhitespace 
        /// is enabled then  is
        /// set to .  See  
        /// for more information on whitespace handling.
        /// 
        /// 
        /// A string containing XML. 
        /// 
        ///  
        /// A set of . 
        /// 
        ///  
        /// An  containing an XML tree initialized from the
        /// passed in XML string.
        /// 
        public static XDocument Parse(string text, LoadOptions options) { 
            using (StringReader sr = new StringReader(text)) {
                XmlReaderSettings rs = GetXmlReaderSettings(options); 
                using (XmlReader r = XmlReader.Create(sr, rs)) { 
                    return Load(r, options);
                } 
            }
        }

        /// 
        /// Outputs this 's underlying XML tree.  The output can
        /// be saved to a file, an , a , 
        /// or an .  Optionally whitespace can be preserved. 
        /// 
        ///  
        /// Output this  to a file.
        /// 
        /// 
        /// The format will be indented by default.  If you want 
        /// no indenting then use the SaveOptions version of Save (see
        /// ) enabling 
        /// SaveOptions.DisableFormatting. 
        /// 
        ///  
        /// The name of the file to output the XML to.
        /// 
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None); 
        }
 
        ///  
        /// Output this  to a file.
        ///  
        /// 
        /// The name of the file to output the XML to.
        /// 
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            if (declaration != null && !string.IsNullOrEmpty(declaration.Encoding)) { 
                try {
                    ws.Encoding = Encoding.GetEncoding(declaration.Encoding);
                }
                catch (ArgumentException) { 
                }
            } 
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) { 
                Save(w);
            } 
        }

        /// 
        /// Output this  to the passed in . 
        /// 
        ///  
        /// The format will be indented by default.  If you want 
        /// no indenting then use the SaveOptions version of Save (see
        /// ) enabling 
        /// SaveOptions.DisableFormatting
        /// 
        /// 
        /// The  to output this  to. 
        /// 
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None); 
        }
 
        /// 
        /// Output this  to a .
        /// 
        ///  
        /// The  to output the XML to.
        ///  
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) {
                Save(w); 
            }
        } 
 
        /// 
        /// Output this  to an . 
        /// 
        /// 
        /// The  to output the XML to.
        ///  
        public void Save(XmlWriter writer) {
            WriteTo(writer); 
        } 

 
        /// 
        /// Output this 's underlying XML tree to the
        /// passed in .
        ///  
        /// 
        ///  
        /// The  to output the content of this 
        /// .
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer");
            if (declaration != null && declaration.Standalone == "yes") {
                writer.WriteStartDocument(true); 
            }
            else if (declaration != null && declaration.Standalone == "no") { 
                writer.WriteStartDocument(false); 
            }
            else { 
                writer.WriteStartDocument();
            }
            WriteContentTo(writer);
            writer.WriteEndDocument(); 
        }
 
        internal override void  AddAttribute(XAttribute a) { 
            throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
        } 

        internal override void  AddAttributeSkipNotify(XAttribute a) {
            throw new ArgumentException(Res.GetString(Res.Argument_AddAttribute));
        } 

        internal override XNode CloneNode() { 
            return new XDocument(this); 
        }
 
        internal override bool DeepEquals(XNode node) {
            XDocument other = node as XDocument;
            return other != null && ContentsEqual(other);
        } 

        internal override int GetDeepHashCode() { 
            return ContentsHashCode(); 
        }
 
        T GetFirstNode() where T : XNode {
            XNode n = content as XNode;
            if (n != null) {
                do { 
                    n = n.next;
                    T e = n as T; 
                    if (e != null) return e; 
                } while (n != content);
            } 
            return null;
        }

        internal static bool IsWhitespace(string s) { 
            foreach (char ch in s) {
                if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') return false; 
            } 
            return true;
        } 

        internal override void ValidateNode(XNode node, XNode previous) {
            switch (node.NodeType) {
                case XmlNodeType.Text: 
                    ValidateString(((XText)node).Value);
                    break; 
                case XmlNodeType.Element: 
                    ValidateDocument(previous, XmlNodeType.DocumentType, XmlNodeType.None);
                    break; 
                case XmlNodeType.DocumentType:
                    ValidateDocument(previous, XmlNodeType.None, XmlNodeType.Element);
                    break;
                case XmlNodeType.CDATA: 
                    throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.CDATA));
                case XmlNodeType.Document: 
                    throw new ArgumentException(Res.GetString(Res.Argument_AddNode, XmlNodeType.Document)); 
            }
        } 

        void ValidateDocument(XNode previous, XmlNodeType allowBefore, XmlNodeType allowAfter) {
            XNode n = content as XNode;
            if (n != null) { 
                if (previous == null) allowBefore = allowAfter;
                do { 
                    n = n.next; 
                    XmlNodeType nt = n.NodeType;
                    if (nt == XmlNodeType.Element || nt == XmlNodeType.DocumentType) { 
                        if (nt != allowBefore) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_DocumentStructure));
                        allowBefore = XmlNodeType.None;
                    }
                    if (n == previous) allowBefore = allowAfter; 
                } while (n != content);
            } 
        } 

        internal override void ValidateString(string s) { 
            if (!IsWhitespace(s)) throw new ArgumentException(Res.GetString(Res.Argument_AddNonWhitespace));
        }
    }
 
    /// 
    /// Represents an XML comment. 
    ///  
    public class XComment : XNode
    { 
        internal string value;

        /// 
        /// Initializes a new instance of the  class. 
        /// 
        ///  
        /// Initializes a new instance of the  class with the 
        /// specified string content.
        ///  
        /// 
        /// The contents of the new XComment object.
        /// 
        ///  
        /// Thrown if the specified value is null.
        ///  
        public XComment(string value) { 
            if (value == null) throw new ArgumentNullException("value");
            this.value = value; 
        }

        /// 
        /// Initializes a new comment node from an existing comment node. 
        /// 
        /// Comment node to copy from. 
        public XComment(XComment other) { 
            if (other == null) throw new ArgumentNullException("other");
            this.value = other.value; 
        }

        internal XComment(XmlReader r) {
            value = r.Value; 
            r.Read();
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.Comment.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.Comment; 
            }
        } 

        /// 
        /// Gets or sets the string value of this comment.
        ///  
        /// 
        /// Thrown if the specified value is null. 
        ///  
        public string Value {
            get { 
                return value;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                this.value = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 

        /// 
        /// Write this  to the passed in .
        ///  
        /// 
        /// The  to write this  to. 
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteComment(value);
        }

        internal override XNode CloneNode() { 
            return new XComment(this);
        } 
 
        internal override bool DeepEquals(XNode node) {
            XComment other = node as XComment; 
            return other != null && value == other.value;
        }

        internal override int GetDeepHashCode() { 
            return value.GetHashCode();
        } 
    } 

    ///  
    /// Represents an XML processing instruction.
    /// 
    public class XProcessingInstruction : XNode
    { 
        internal string target;
        internal string data; 
 
        /// 
        /// Initializes a new XML Processing Instruction from the specified target and string data. 
        /// 
        /// 
        /// The target application for this .
        ///  
        /// 
        /// The string data that comprises the . 
        ///  
        /// 
        /// Thrown if either the target or data parameter are null. 
        /// 
        public XProcessingInstruction(string target, string data) {
            if (data == null) throw new ArgumentNullException("data");
            ValidateName(target); 
            this.target = target;
            this.data = data; 
        } 

        ///  
        /// Initializes a new XML processing instruction by copying its target and data
        /// from another XML processing instruction.
        /// 
        /// XML processing instruction to copy from. 
        public XProcessingInstruction(XProcessingInstruction other) {
            if (other == null) throw new ArgumentNullException("other"); 
            this.target = other.target; 
            this.data = other.data;
        } 

        internal XProcessingInstruction(XmlReader r) {
            target = r.Name;
            data = r.Value; 
            r.Read();
        } 
 
        /// 
        /// Gets or sets the string value of this processing instruction. 
        /// 
        /// 
        /// Thrown if the value set is null.
        ///  
        public string Data {
            get { 
                return data; 
            }
            set { 
                if (value == null) throw new ArgumentNullException("value");
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                data = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.ProcessingInstruction.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.ProcessingInstruction; 
            }
        } 

        /// 
        /// Gets or sets a string representing the target application for this processing instruction.
        ///  
        /// 
        /// Thrown if the value set is null. 
        ///  
        public string Target {
            get { 
                return target;
            }
            set {
                ValidateName(value); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                target = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name); 
            }
        } 

        /// 
        /// Writes this  to the passed in .
        ///  
        /// 
        /// The  to write this  to. 
        ///  
        public override void WriteTo(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteProcessingInstruction(target, data);
        }

        internal override XNode CloneNode() { 
            return new XProcessingInstruction(this);
        } 
 
        internal override bool DeepEquals(XNode node) {
            XProcessingInstruction other = node as XProcessingInstruction; 
            return other != null && target == other.target && data == other.data;
        }

        internal override int GetDeepHashCode() { 
            return target.GetHashCode() ^ data.GetHashCode();
        } 
 
        static void ValidateName(string name) {
            XmlConvert.VerifyNCName(name); 
            if (string.Compare(name, "xml", StringComparison.OrdinalIgnoreCase) == 0) throw new ArgumentException(Res.GetString(Res.Argument_InvalidPIName, name));
        }
    }
 
    /// 
    /// Represents an XML declaration. 
    ///  
    /// 
    /// An XML declaration is used to declare the XML version, 
    /// the encoding, and whether or not the XML document is standalone.
    /// 
    public class XDeclaration
    { 
        string version;
        string encoding; 
        string standalone; 

        ///  
        /// Initilizes a new instance of the  class from the
        /// specified version, encoding, and standalone properties.
        /// 
        ///  
        /// The version of the XML, usually "1.0".
        ///  
        ///  
        /// The encoding for the XML document.
        ///  
        /// 
        /// Specifies whether the XML is standalone or requires external entities
        /// to be resolved.
        ///  
        public XDeclaration(string version, string encoding, string standalone) {
            this.version = version; 
            this.encoding = encoding; 
            this.standalone = standalone;
        } 

        /// 
        /// Initializes an instance of the  class
        /// from another  object. 
        /// 
        ///  
        /// The  used to initialize this  object. 
        /// 
        public XDeclaration(XDeclaration other) { 
            if (other == null) throw new ArgumentNullException("other");
            version = other.version;
            encoding = other.encoding;
            standalone = other.standalone; 
        }
 
        internal XDeclaration(XmlReader r) { 
            version = r.GetAttribute("version");
            encoding = r.GetAttribute("encoding"); 
            standalone = r.GetAttribute("standalone");
            r.Read();
        }
 
        /// 
        /// Gets or sets the encoding for this document. 
        ///  
        public string Encoding {
            get { return encoding; } 
            set { encoding = value; }
        }

        ///  
        /// Gets or sets the standalone property for this document.
        ///  
        ///  
        /// The valid values for standalone are "yes" or "no".
        ///  
        public string Standalone {
            get { return standalone; }
            set { standalone = value; }
        } 

        ///  
        /// Gets or sets the version property for this document. 
        /// 
        ///  
        /// The value is usually "1.0".
        /// 
        public string Version {
            get { return version; } 
            set { version = value; }
        } 
 
        /// 
        /// Provides a formatted string. 
        /// 
        /// A formatted XML string.
        public override string ToString() {
            StringBuilder sb = new StringBuilder("");
            return sb.ToString();
        } 
    }
 
    ///  
    /// Represents an XML Document Type Definition (DTD).
    ///  
    public class XDocumentType : XNode
    {
        string name;
        string publicId; 
        string systemId;
        string internalSubset; 
 
        /// 
        /// Initializes an empty instance of the  class. 
        /// 
        public XDocumentType(string name, string publicId, string systemId, string internalSubset) {
            this.name = XmlConvert.VerifyName(name);
            this.publicId = publicId; 
            this.systemId = systemId;
            this.internalSubset = internalSubset; 
        } 

        ///  
        /// Initializes an instance of the XDocumentType class
        /// from another XDocumentType object.
        /// 
        ///  object to copy from. 
        public XDocumentType(XDocumentType other) {
            if (other == null) throw new ArgumentNullException("other"); 
            this.name = other.name; 
            this.publicId = other.publicId;
            this.systemId = other.systemId; 
            this.internalSubset = other.internalSubset;
        }

        internal XDocumentType(XmlReader r) { 
            name = r.Name;
            publicId = r.GetAttribute("PUBLIC"); 
            systemId = r.GetAttribute("SYSTEM"); 
            internalSubset = r.Value;
            r.Read(); 
        }

        /// 
        /// Gets or sets the internal subset for this Document Type Definition (DTD). 
        /// 
        public string InternalSubset { 
            get { 
                return internalSubset;
            } 
            set {
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                internalSubset = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        } 
 
        /// 
        /// Gets or sets the name for this Document Type Definition (DTD). 
        /// 
        public string Name {
            get {
                return name; 
            }
            set { 
                value = XmlConvert.VerifyName(value); 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Name);
                name = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Name);
            }
        }
 
        /// 
        /// Gets the node type for this node. 
        ///  
        /// 
        /// This property will always return XmlNodeType.DocumentType. 
        /// 
        public override XmlNodeType NodeType {
            get {
                return XmlNodeType.DocumentType; 
            }
        } 
 
        /// 
        /// Gets or sets the public identifier for this Document Type Definition (DTD). 
        /// 
        public string PublicId {
            get {
                return publicId; 
            }
            set { 
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                publicId = value;
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value); 
            }
        }

        ///  
        /// Gets or sets the system identifier for this Document Type Definition (DTD).
        ///  
        public string SystemId { 
            get {
                return systemId; 
            }
            set {
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value);
                systemId = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value);
            } 
        } 

        ///  
        /// Write this  to the passed in .
        /// 
        /// 
        /// The  to write this  to. 
        /// 
        public override void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteDocType(name, publicId, systemId, internalSubset);
        } 

        internal override XNode CloneNode() {
            return new XDocumentType(this);
        } 

        internal override bool DeepEquals(XNode node) { 
            XDocumentType other = node as XDocumentType; 
            return other != null && name == other.name && publicId == other.publicId &&
                systemId == other.SystemId && internalSubset == other.internalSubset; 
        }

        internal override int GetDeepHashCode() {
            return name.GetHashCode() ^ 
                (publicId != null ? publicId.GetHashCode() : 0) ^
                (systemId != null ? systemId.GetHashCode() : 0) ^ 
                (internalSubset != null ? internalSubset.GetHashCode() : 0); 
        }
    } 

    /// 
    /// Represents an XML attribute.
    ///  
    /// 
    /// An XML attribute is a name/value pair associated with an XML element. 
    ///  
    [System.ComponentModel.TypeDescriptionProvider(typeof(ComponentModel.XTypeDescriptionProvider))]
    [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "Reviewed.")] 
    public class XAttribute : XObject
    {
        static IEnumerable emptySequence;
 
        /// 
        /// Gets an empty collection of attributes. 
        ///  
        public static IEnumerable EmptySequence {
            get { 
                if (emptySequence == null) emptySequence = new XAttribute[0];
                return emptySequence;
            }
        } 

        internal XAttribute next; 
        internal XName name; 
        internal string value;
 
        /// 
        /// Initializes a new instance of the  class.
        /// 
        ///  
        /// Initializes a new instance of the  class from
        /// the specified name and value. 
        ///  
        /// 
        /// The name of the attribute. 
        /// 
        /// 
        /// The value of the attribute.
        ///  
        /// 
        /// Thrown if the passed in name or value are null. 
        ///  
        public XAttribute(XName name, object value) {
            if (name == null) throw new ArgumentNullException("name"); 
            if (value == null) throw new ArgumentNullException("value");
            string s = XContainer.GetStringValue(value);
            ValidateAttribute(name, s);
            this.name = name; 
            this.value = s;
        } 
 
        /// 
        /// Initializes an instance of the XAttribute class 
        /// from another XAttribute object.
        /// 
        ///  object to copy from.
        ///  
        /// Thrown if the specified  is null.
        ///  
        public XAttribute(XAttribute other) { 
            if (other == null) throw new ArgumentNullException("other");
            name = other.name; 
            value = other.value;
        }

        ///  
        /// Gets a value indicating if this attribute is a namespace declaration.
        ///  
        public bool IsNamespaceDeclaration { 
            get {
                string namespaceName = name.NamespaceName; 
                if (namespaceName.Length == 0) {
                    return name.LocalName == "xmlns";
                }
                return (object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace; 
            }
        } 
 
        /// 
        /// Gets the name of this attribute. 
        /// 
        public XName Name {
            get { return name; }
        } 

        ///  
        /// Gets the next attribute of the parent element. 
        /// 
        ///  
        /// If this attribute does not have a parent, or if there is no next attribute,
        /// then this property returns null.
        /// 
        public XAttribute NextAttribute { 
            get { return parent != null && ((XElement)parent).lastAttr != this ? next : null; }
        } 
 
        /// 
        /// Gets the node type for this node. 
        /// 
        /// 
        /// This property will always return XmlNodeType.Attribute.
        ///  
        public override XmlNodeType NodeType {
            get { 
                return XmlNodeType.Attribute; 
            }
        } 

        /// 
        /// Gets the previous attribute of the parent element.
        ///  
        /// 
        /// If this attribute does not have a parent, or if there is no previous attribute, 
        /// then this property returns null. 
        /// 
        public XAttribute PreviousAttribute { 
            get {
                if (parent == null) return null;
                XAttribute a = ((XElement)parent).lastAttr;
                while (a.next != this) { 
                    a = a.next;
                } 
                return a != ((XElement)parent).lastAttr ? a : null; 
            }
        } 

        /// 
        /// Gets or sets the value of this attribute.
        ///  
        /// 
        /// Thrown if the value set is null. 
        ///  
        public string Value {
            get { 
                return value;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                ValidateAttribute(name, value);
                bool notify = NotifyChanging(this, XObjectChangeEventArgs.Value); 
                this.value = value; 
                if (notify) NotifyChanged(this, XObjectChangeEventArgs.Value);
            } 
        }

        /// 
        /// Deletes this XAttribute. 
        /// 
        ///  
        /// Thrown if the parent element is null. 
        /// 
        public void Remove() { 
            if (parent == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_MissingParent));
            ((XElement)parent).RemoveAttribute(this);
        }
 
        /// 
        /// Sets the value of this . 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// The value to assign to this attribute. The value is converted to its string
        /// representation and assigned to the  property. 
        /// 
        ///  
        /// Thrown if the specified value is null. 
        /// 
        public void SetValue(object value) { 
            if (value == null) throw new ArgumentNullException("value");
            Value = XContainer.GetStringValue(value);
        }
 
        /// 
        /// Override for  on  
        ///  
        /// XML text representation of an attribute and its value
        public override string ToString() { 
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) {
                XmlWriterSettings ws = new XmlWriterSettings();
                ws.ConformanceLevel = ConformanceLevel.Fragment;
                using (XmlWriter w = XmlWriter.Create(sw, ws)) { 
                    w.WriteAttributeString(GetPrefixOfNamespace(name.Namespace), name.LocalName, name.NamespaceName, value);
                } 
                return sw.ToString().Trim(); 
            }
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        [CLSCompliant(false)]
        public static explicit operator string(XAttribute attribute) {
            if (attribute == null) return null; 
            return attribute.value;
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator bool(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToBoolean(attribute.value.ToLower(CultureInfo.InvariantCulture));
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator bool?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToBoolean(attribute.value.ToLower(CultureInfo.InvariantCulture));
        }
 
        /// 
        /// Cast the value of this  to an . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as an .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator int(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToInt32(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as an ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator int?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToInt32(attribute.value);
        } 

        /// 
        /// Cast the value of this  to an .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as an . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator uint(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToUInt32(attribute.value);
        } 

        /// 
        /// Cast the value of this  to an ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as an ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator uint?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToUInt32(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator long(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToInt64(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator long?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToInt64(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to an . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as an .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator ulong(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToUInt64(attribute.value);
        }
 
         /// 
        /// Cast the value of this  to an ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as an ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator ulong?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToUInt64(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator float(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToSingle(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator float?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToSingle(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator double(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToDouble(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator double?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToDouble(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator decimal(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToDecimal(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator decimal?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToDecimal(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator DateTime(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator DateTime?(XAttribute attribute) {
            if (attribute == null) return null; 
            return DateTime.Parse(attribute.value, CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind);
        } 
 
        /// 
        /// Cast the value of this  to a . 
        /// 
        /// 
        /// The  to cast to .
        ///  
        /// 
        /// The content of this  as a . 
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator DateTimeOffset(XAttribute attribute) {
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToDateTimeOffset(attribute.value);
        } 
 
        /// 
        /// Cast the value of this  to a ?. 
        /// 
        /// 
        /// The  to cast to ?. Can be null.
        ///  
        /// 
        /// The content of this  as a ?. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator DateTimeOffset?(XAttribute attribute) { 
            if (attribute == null) return null;
            return XmlConvert.ToDateTimeOffset(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a . 
        ///  
        /// 
        /// The  to cast to . 
        /// 
        /// 
        /// The content of this  as a .
        ///  
        /// 
        /// Thrown if the specified attribute is null. 
        ///  
        [CLSCompliant(false)]
        public static explicit operator TimeSpan(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute");
            return XmlConvert.ToTimeSpan(attribute.value);
        }
 
        /// 
        /// Cast the value of this  to a ?. 
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        /// 
        /// 
        /// The content of this  as a ?.
        ///  
        [CLSCompliant(false)]
        public static explicit operator TimeSpan?(XAttribute attribute) { 
            if (attribute == null) return null; 
            return XmlConvert.ToTimeSpan(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a .
        ///  
        /// 
        /// The  to cast to . 
        ///  
        /// 
        /// The content of this  as a . 
        /// 
        /// 
        /// Thrown if the specified attribute is null.
        ///  
        [CLSCompliant(false)]
        public static explicit operator Guid(XAttribute attribute) { 
            if (attribute == null) throw new ArgumentNullException("attribute"); 
            return XmlConvert.ToGuid(attribute.value);
        } 

        /// 
        /// Cast the value of this  to a ?.
        ///  
        /// 
        /// The  to cast to ?. Can be null. 
        ///  
        /// 
        /// The content of this  as a ?. 
        /// 
        [CLSCompliant(false)]
        public static explicit operator Guid?(XAttribute attribute) {
            if (attribute == null) return null; 
            return XmlConvert.ToGuid(attribute.value);
        } 
 
        internal int GetDeepHashCode() {
            return name.GetHashCode() ^ value.GetHashCode(); 
        }

        internal string GetPrefixOfNamespace(XNamespace ns) {
            string namespaceName = ns.NamespaceName; 
            if (namespaceName.Length == 0) return string.Empty;
            if (parent != null) return ((XElement)parent).GetPrefixOfNamespace(ns); 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml"; 
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns";
            return null; 
        }

        static void ValidateAttribute(XName name, string value) {
            // The following constraints apply for namespace declarations: 
            string namespaceName = name.NamespaceName;
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) { 
                if (value.Length == 0) { 
                    // The empty namespace name can only be declared by
                    // the default namespace declaration 
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationPrefixed, name.LocalName));
                }
                else if (value == XNamespace.xmlPrefixNamespace) {
                    // 'http://www.w3.org/XML/1998/namespace' can only 
                    // be declared by the 'xml' prefix namespace declaration.
                    if (name.LocalName != "xml") throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml)); 
                } 
                else if (value == XNamespace.xmlnsPrefixNamespace) {
                    // 'http://www.w3.org/2000/xmlns/' must not be declared 
                    // by any namespace declaration.
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns));
                }
                else { 
                    string localName = name.LocalName;
                    if (localName == "xml") { 
                        // No other namespace name can be declared by the 'xml' 
                        // prefix namespace declaration.
                        throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml)); 
                    }
                    else if (localName == "xmlns") {
                        // The 'xmlns' prefix must not be declared.
                        throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns)); 
                    }
                } 
            } 
            else if (namespaceName.Length == 0 && name.LocalName == "xmlns") {
                if (value == XNamespace.xmlPrefixNamespace) { 
                    // 'http://www.w3.org/XML/1998/namespace' can only
                    // be declared by the 'xml' prefix namespace declaration.
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXml));
                } 
                else if (value == XNamespace.xmlnsPrefixNamespace) {
                    // 'http://www.w3.org/2000/xmlns/' must not be declared 
                    // by any namespace declaration. 
                    throw new ArgumentException(Res.GetString(Res.Argument_NamespaceDeclarationXmlns));
                } 
            }
        }
    }
 
    /// 
    /// Represents a class that allows elements to be streamed 
    /// on input and output. 
    /// 
    public class XStreamingElement 
    {
        internal XName name;
        internal object content;
 
        /// 
        ///  Creates a  node with a given name 
        ///  
        /// The name to assign to the new  node
        public XStreamingElement(XName name) { 
            if (name == null) throw new ArgumentNullException("name");
            this.name = name;
        }
 
        /// 
        /// Creates a  node with a given name and content 
        ///  
        /// The name to assign to the new  node
        /// The content to assign to the new  node 
        public XStreamingElement(XName name, object content) : this(name) {
            this.content = content is List? new object[] { content } : content;
        }
 
        /// 
        /// Creates a  node with a given name and content 
        ///  
        /// The name to assign to the new  node
        /// An array containing content to assign to the new  node 
        public XStreamingElement(XName name, params object[] content) : this(name) {
            this.content = content;
        }
 
        /// 
        /// Gets or sets the name of this streaming element. 
        ///  
        public XName Name {
            get { 
                return name;
            }
            set {
                if (value == null) throw new ArgumentNullException("value"); 
                name = value;
            } 
        } 

        ///  
        /// Add content to an 
        /// 
        /// Object containg content to add
        public void Add(object content) { 
            if (content != null) {
                List list = this.content as List; 
                if (list == null) { 
                    list = new List();
                    if (this.content != null) list.Add(this.content); 
                    this.content = list;
                }
                list.Add(content);
            } 
        }
 
        ///  
        /// Add content to an 
        ///  
        /// array of objects containg content to add
        public void Add(params object[] content) {
            Add((object)content);
        } 

 
        ///  
        /// Save an  to a file with formatting.
        ///  
        /// Name of file to write content to
        public void Save(string fileName) {
            Save(fileName, SaveOptions.None);
        } 

        ///  
        /// Save an  to a file, optionally formatting. 
        /// 
        /// Name of file to write content to 
        /// 
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        /// 
        public void Save(string fileName, SaveOptions options) { 
            XmlWriterSettings ws = XNode.GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(fileName, ws)) { 
                Save(w); 
            }
        } 

        /// 
        /// Save the contents of an  to a text writer
        /// with formatting. 
        /// 
        ///  to write to  
        public void Save(TextWriter textWriter) { 
            Save(textWriter, SaveOptions.None);
        } 

        /// 
        /// Save the contents of an  to a text writer
        /// optionally formatting. 
        /// 
        ///  to write to  
        ///  
        /// If SaveOptions.DisableFormatting is enabled the output is not indented.
        ///  
        public void Save(TextWriter textWriter, SaveOptions options) {
            XmlWriterSettings ws = XNode.GetXmlWriterSettings(options);
            using (XmlWriter w = XmlWriter.Create(textWriter, ws)) {
                Save(w); 
            }
        } 
 
        /// 
        /// Save the contents of an  to an XML writer, not preserving whitepace 
        /// 
        ///  to write to 
        public void Save(XmlWriter writer) {
            if (writer == null) throw new ArgumentNullException("writer"); 
            writer.WriteStartDocument();
            WriteTo(writer); 
            writer.WriteEndDocument(); 
        }
 
        /// 
        /// Get the XML content of an  as a
        /// formatted string.
        ///  
        /// The XML text as a formatted string
        public override string ToString() { 
            return GetXmlString(SaveOptions.None); 
        }
 
        /// 
        /// Gets the XML content of this streaming element as a string.
        /// 
        /// If SaveOptions.DisableFormatting is enabled the 
        /// content is not indented.
        /// An XML string 
        public string ToString(SaveOptions options) { 
            return GetXmlString(options);
        } 

        /// 
        /// Write this  to an 
        ///  
        /// 
        public void WriteTo(XmlWriter writer) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            new StreamingElementWriter(writer).WriteStreamingElement(this);
        } 

        string GetXmlString(SaveOptions o) {
            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture)) {
                XmlWriterSettings ws = new XmlWriterSettings(); 
                ws.OmitXmlDeclaration = true;
                if ((o & SaveOptions.DisableFormatting) == 0) ws.Indent = true; 
                using (XmlWriter w = XmlWriter.Create(sw, ws)) { 
                    WriteTo(w);
                } 
                return sw.ToString();
            }
        }
    } 

    internal struct StreamingElementWriter 
    { 
        XmlWriter writer;
        XStreamingElement element; 
        List attributes;
        NamespaceResolver resolver;

        public StreamingElementWriter(XmlWriter w) { 
            writer = w;
            element = null; 
            attributes = new List(); 
            resolver = new NamespaceResolver();
        } 

        void FlushElement() {
            if (element != null) {
                PushElement(); 
                XNamespace ns = element.Name.Namespace;
                writer.WriteStartElement(GetPrefixOfNamespace(ns, true), element.Name.LocalName, ns.NamespaceName); 
                foreach (XAttribute a in attributes) { 
                    ns = a.Name.Namespace;
                    string localName = a.Name.LocalName; 
                    string namespaceName = ns.NamespaceName;
                    writer.WriteAttributeString(GetPrefixOfNamespace(ns, false), localName, namespaceName.Length == 0 && localName == "xmlns" ? XNamespace.xmlnsPrefixNamespace : namespaceName, a.Value);
                }
                element = null; 
                attributes.Clear();
            } 
        } 

        string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace) { 
            string namespaceName = ns.NamespaceName;
            if (namespaceName.Length == 0) return string.Empty;
            string prefix = resolver.GetPrefixOfNamespace(ns, allowDefaultNamespace);
            if (prefix != null) return prefix; 
            if ((object)namespaceName == (object)XNamespace.xmlPrefixNamespace) return "xml";
            if ((object)namespaceName == (object)XNamespace.xmlnsPrefixNamespace) return "xmlns"; 
            return null; 
        }
 
        void PushElement() {
            resolver.PushScope();
            foreach (XAttribute a in attributes) {
                if (a.IsNamespaceDeclaration) { 
                    resolver.Add(a.Name.NamespaceName.Length == 0 ? string.Empty : a.Name.LocalName, XNamespace.Get(a.Value));
                } 
            } 
        }
 
        void Write(object content) {
            if (content == null) return;
            XNode n = content as XNode;
            if (n != null) { 
                WriteNode(n);
                return; 
            } 
            string s = content as string;
            if (s != null) { 
                WriteString(s);
                return;
            }
            XAttribute a = content as XAttribute; 
            if (a != null) {
                WriteAttribute(a); 
                return; 
            }
            XStreamingElement x = content as XStreamingElement; 
            if (x != null) {
                WriteStreamingElement(x);
                return;
            } 
            object[] o = content as object[];
            if (o != null) { 
                foreach (object obj in o) Write(obj); 
                return;
            } 
            IEnumerable e = content as IEnumerable;
            if (e != null) {
                foreach (object obj in e) Write(obj);
                return; 
            }
            WriteString(XContainer.GetStringValue(content)); 
        } 

        void WriteAttribute(XAttribute a) { 
            if (element == null) throw new InvalidOperationException(Res.GetString(Res.InvalidOperation_WriteAttribute));
            attributes.Add(a);
        }
 
        void WriteNode(XNode n) {
            FlushElement(); 
            n.WriteTo(writer); 
        }
 
        internal void WriteStreamingElement(XStreamingElement e) {
            FlushElement();
            element = e;
            Write(e.content); 
            bool contentWritten = element == null;
            FlushElement(); 
            if (contentWritten) { 
                writer.WriteFullEndElement();
            } 
            else {
                writer.WriteEndElement();
            }
            resolver.PopScope(); 
        }
 
        void WriteString(string s) { 
            FlushElement();
            writer.WriteString(s); 
        }
    }

    ///  
    /// Defines the LINQ to XML extension methods.
    ///  
    public static class Extensions 
    {
        ///  
        /// Returns all of the s for each  of
        /// this  of .
        /// 
        ///  
        /// An  of  containing the XML
        /// Attributes for every  in the target  
        /// of . 
        /// 
        public static IEnumerable Attributes(this IEnumerable source) { 
            if (source == null) throw new ArgumentNullException("source");
            return GetAttributes(source, null);
        }
 
        /// 
        /// Returns the s that have a matching .  Each 
        /// 's s in the target  
        /// of  are scanned for a matching .
        ///  
        /// 
        /// An  of  containing the XML
        /// Attributes with a matching  for every  in
        /// the target  of . 
        /// 
        public static IEnumerable Attributes(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetAttributes(source, name) : XAttribute.EmptySequence;
        } 

        /// 
        /// Returns an  of  containing the ancestors (parent
        /// and it's parent up to the root) of each of the s in this 
        ///  of .
        ///  
        ///  
        /// An  of  containing the ancestors (parent
        /// and it's parent up to the root) of each of the s in this 
        ///  of .
        /// 
        public static IEnumerable Ancestors(this IEnumerable source) where T: XNode {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetAncestors(source, null, false);
        } 
 
        /// 
        /// Returns an  of  containing the ancestors (parent 
        /// and it's parent up to the root) that have a matching .  This is done for each
        ///  in this  of .
        /// 
        ///  
        /// An  of  containing the ancestors (parent
        /// and it's parent up to the root) that have a matching .  This is done for each 
        ///  in this  of . 
        /// 
        public static IEnumerable Ancestors(this IEnumerable source, XName name) where T: XNode { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetAncestors(source, name, false) : XElement.EmptySequence;
        }
 
        /// 
        /// Returns an  of  containing the 
        ///  and it's ancestors (parent and it's parent up to the root). 
        /// This is done for each  in this  of
        /// . 
        /// 
        /// 
        /// An  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root). 
        /// This is done for each  in this  of
        /// . 
        ///  
        public static IEnumerable AncestorsAndSelf(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetAncestors(source, null, true);
        }

        ///  
        /// Returns an  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root) 
        /// that match the passed in .  This is done for each 
        ///  in this  of .
        ///  
        /// 
        /// An  of  containing the
        ///  and it's ancestors (parent and it's parent up to the root)
        /// that match the passed in .  This is done for each 
        ///  in this  of .
        ///  
        public static IEnumerable AncestorsAndSelf(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetAncestors(source, name, true) : XElement.EmptySequence; 
        }

        /// 
        /// Returns an  of  over the content of a set of nodes 
        /// 
        public static IEnumerable Nodes(this IEnumerable source) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source"); 
            foreach (XContainer root in source) {
                if (root != null) { 
                    XNode n = root.LastNode;
                    if (n != null) {
                        do {
                            n = n.next; 
                            yield return n;
                        } while (n.parent == root && n != root.content); 
                    } 
                }
            } 
        }

        /// 
        /// Returns an  of  over the descendants of a set of nodes 
        /// 
        public static IEnumerable DescendantNodes(this IEnumerable source) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendantNodes(source, false);
        } 

        /// 
        /// Returns an  of  containing the descendants (children
        /// and their children down to the leaf level).  This is done for each  in 
        /// this  of .
        ///  
        ///  
        /// An  of  containing the descendants (children
        /// and their children down to the leaf level).  This is done for each  in 
        /// this  of .
        /// 
        public static IEnumerable Descendants(this IEnumerable source) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendants(source, null, false);
        } 
 
        /// 
        /// Returns an  of  containing the descendants (children 
        /// and their children down to the leaf level) that have a matching .  This is done
        /// for each  in the target  of .
        /// 
        ///  
        /// An  of  containing the descendants (children
        /// and their children down to the leaf level) that have a matching .  This is done 
        /// for each  in this  of . 
        /// 
        public static IEnumerable Descendants(this IEnumerable source, XName name) where T: XContainer { 
            if (source == null) throw new ArgumentNullException("source");
            return name != null ? GetDescendants(source, name, false) : XElement.EmptySequence;
        }
 
        /// 
        /// Returns an  of  containing the 
        ///  and it's descendants 
        /// that match the passed in .  This is done for each
        ///  in this  of . 
        /// 
        /// 
        /// An  of  containing the
        ///  and descendants. 
        /// This is done for each
        ///  in this  of . 
        ///  
        public static IEnumerable DescendantNodesAndSelf(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source"); 
            return GetDescendantNodes(source, true);
        }

        ///  
        /// Returns an  of  containing the
        ///  and it's descendants (children and children's children down 
        /// to the leaf nodes).  This is done for each  in this  
        /// of .
        ///  
        /// 
        /// An  of  containing the
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes).  This is done for each  in this  
        /// of .
        ///  
        public static IEnumerable DescendantsAndSelf(this IEnumerable source) { 
            if (source == null) throw new ArgumentNullException("source");
            return GetDescendants(source, null, true); 
        }

        /// 
        /// Returns an  of  containing the 
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes) that match the passed in .  This is done for 
        /// each  in this  of . 
        /// 
        ///  
        /// An  of  containing the
        ///  and it's descendants (children and children's children down
        /// to the leaf nodes) that match the passed in .  This is done for
        /// each  in this  of . 
        /// 
        public static IEnumerable DescendantsAndSelf(this IEnumerable source, XName name) { 
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetDescendants(source, name, true) : XElement.EmptySequence;
        } 

        /// 
        /// Returns an  of  containing the child elements
        /// for each  in this  of . 
        /// 
        ///  
        /// An  of  containing the child elements 
        /// for each  in this  of .
        ///  
        public static IEnumerable Elements(this IEnumerable source) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source");
            return GetElements(source, null);
        } 

        ///  
        /// Returns an  of  containing the child elements 
        /// with a matching for each  in this  of .
        ///  
        /// 
        /// An  of  containing the child elements
        /// for each  in this  of .
        ///  
        public static IEnumerable Elements(this IEnumerable source, XName name) where T: XContainer {
            if (source == null) throw new ArgumentNullException("source"); 
            return name != null ? GetElements(source, name) : XElement.EmptySequence; 
        }
 
        /// 
        /// Returns an  of  containing the child elements
        /// with a matching for each  in this  of .
        ///  
        /// 
        /// An  of  containing the child elements 
        /// for each  in this  of . 
        /// in document order
        ///  
        public static IEnumerable InDocumentOrder(this IEnumerable source) where T: XNode {
            return Enumerable.OrderBy(source, n => (XNode)n, XNode.DocumentOrderComparer);
        }
 
        /// 
        /// Removes each  represented in this  of 
        /// .  Note that this method uses snapshot semantics (copies the 
        /// attributes to a  before deleting each).
        ///  
        public static void Remove(this IEnumerable source) {
            if (source == null) throw new ArgumentNullException("source");
            foreach (XAttribute a in new List(source))
                if (a != null) a.Remove(); 
        }
 
        ///  
        /// Removes each  represented in this 
        /// T which must be a derived from .  Note that this method uses snapshot semantics 
        /// (copies the s to a List before deleting each).
        /// 
        public static void Remove(this IEnumerable source) where T: XNode {
            if (source == null) throw new ArgumentNullException("source"); 
            foreach (T node in new List(source))
                if (node != null) node.Remove(); 
        } 

        static IEnumerable GetAttributes(IEnumerable source, XName name) { 
            foreach (XElement e in source) {
                if (e != null) {
                    XAttribute a = e.lastAttr;
                    if (a != null) { 
                        do {
                            a = a.next; 
                            if (name == null || a.name == name) yield return a; 
                        } while (a.parent == e && a != e.lastAttr);
                    } 
                }
            }
        }
 
        static IEnumerable GetAncestors(IEnumerable source, XName name, bool self) where T: XNode {
            foreach (XNode node in source) { 
                if (node != null) { 
                    XElement e = (self ? node : node.parent) as XElement;
                    while (e != null) { 
                        if (name == null || e.name == name) yield return e;
                        e = e.parent as XElement;
                    }
                } 
            }
        } 
 
        static IEnumerable GetDescendantNodes(IEnumerable source, bool self) where T: XContainer {
            foreach (XContainer root in source) { 
                if (root != null) {
                    if (self) yield return root;
                    XNode n = root;
                    while (true) { 
                        XContainer c = n as XContainer;
                        XNode first; 
                        if (c != null && (first = c.FirstNode) != null) { 
                            n = first;
                        } 
                        else {
                            while (n != null && n != root && n == n.parent.content) n = n.parent;
                            if (n == null || n == root) break;
                            n = n.next; 
                        }
                        yield return n; 
                    } 
                }
            } 
        }

        static IEnumerable GetDescendants(IEnumerable source, XName name, bool self) where T: XContainer {
            foreach (XContainer root in source) { 
                if (root != null) {
                    if (self) { 
                        XElement e = (XElement)root; 
                        if (name == null || e.name == name) yield return e;
                    } 
                    XNode n = root;
                    XContainer c = root;
                    while (true) {
                        if (c != null && c.content is XNode) { 
                            n = ((XNode)c.content).next;
                        } 
                        else { 
                            while (n != null && n != root && n == n.parent.content) n = n.parent;
                            if (n == null || n == root) break; 
                            n = n.next;
                        }
                        XElement e = n as XElement;
                        if (e != null && (name == null || e.name == name)) yield return e; 
                        c = e;
                    } 
                } 
            }
        } 

        static IEnumerable GetElements(IEnumerable source, XName name) where T: XContainer {
            foreach (XContainer root in source) {
                if (root != null) { 
                    XNode n = root.content as XNode;
                    if (n != null) { 
                        do { 
                            n = n.next;
                            XElement e = n as XElement; 
                            if (e != null && (name == null || e.name == name)) yield return e;
                        } while (n.parent == root && n != root.content);
                    }
                } 
            }
        } 
    } 

    internal class XNodeBuilder : XmlWriter 
    {
        List content;
        XContainer parent;
        XName attrName; 
        string attrValue;
        XContainer root; 
 
        public XNodeBuilder(XContainer container) {
            root = container; 
        }

        public override XmlWriterSettings Settings {
            get { 
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.ConformanceLevel = ConformanceLevel.Auto; 
                return settings; 
            }
        } 

        public override WriteState WriteState {
            get { throw new NotSupportedException(); } // nop
        } 

        public override void Close() { 
            root.Add(content); 
        }
 
        public override void Flush() {
        }

        public override string LookupPrefix(string namespaceName) { 
            throw new NotSupportedException(); // nop
        } 
 
        public override void WriteBase64(byte[] buffer, int index, int count) {
            throw new NotSupportedException(Res.GetString(Res.NotSupported_WriteBase64)); 
        }

        public override void WriteCData(string text) {
            AddNode(new XCData(text)); 
        }
 
        public override void WriteCharEntity(char ch) { 
            AddString(new string(ch, 1));
        } 

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

        public override void WriteComment(string text) { 
            AddNode(new XComment(text)); 
        }
 
        public override void WriteDocType(string name, string pubid, string sysid, string subset) {
            AddNode(new XDocumentType(name, pubid, sysid, subset));
        }
 
        public override void WriteEndAttribute() {
            XAttribute a = new XAttribute(attrName, attrValue); 
            attrName = null; 
            attrValue = null;
            if (parent != null) { 
                parent.Add(a);
            }
            else {
                Add(a); 
            }
        } 
 
        public override void WriteEndDocument() {
        } 

        public override void WriteEndElement() {
            parent = ((XElement)parent).parent;
        } 

        public override void WriteEntityRef(string name) { 
            switch (name) { 
                case "amp":
                    AddString("&"); 
                    break;
                case "apos":
                    AddString("'");
                    break; 
                case "gt":
                    AddString(">"); 
                    break; 
                case "lt":
                    AddString("<"); 
                    break;
                case "quot":
                    AddString("\"");
                    break; 
                default:
                    throw new NotSupportedException(Res.GetString(Res.NotSupported_WriteEntityRef)); 
            } 
        }
 
        public override void WriteFullEndElement() {
            XElement e = (XElement)parent;
            if (e.IsEmpty) {
                e.Add(string.Empty); 
            }
            parent = e.parent; 
        } 

        public override void WriteProcessingInstruction(string name, string text) { 
            if (name == "xml") {
                return;
            }
            AddNode(new XProcessingInstruction(name, text)); 
        }
 
        public override void WriteRaw(char[] buffer, int index, int count) { 
            AddString(new string(buffer, index, count));
        } 

        public override void WriteRaw(string data) {
            AddString(data);
        } 

        public override void WriteStartAttribute(string prefix, string localName, string namespaceName) { 
            if (prefix == null) throw new ArgumentNullException("prefix"); 
            attrName = XNamespace.Get(prefix.Length == 0 ? string.Empty : namespaceName).GetName(localName);
            attrValue = string.Empty; 
        }

        public override void WriteStartDocument() {
        } 

        public override void WriteStartDocument(bool standalone) { 
        } 

        public override void WriteStartElement(string prefix, string localName, string namespaceName) { 
            AddNode(new XElement(XNamespace.Get(namespaceName).GetName(localName)));
        }

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

        public override void WriteWhitespace(string ws) {
            AddString(ws); 
        }
 
        void Add(object o) { 
            if (content == null) {
                content = new List(); 
            }
            content.Add(o);
        }
 
        void AddNode(XNode n) {
            if (parent != null) { 
                parent.Add(n); 
            }
            else { 
                Add(n);
            }
            XContainer c = n as XContainer;
            if (c != null) { 
                parent = c;
            } 
        } 

        void AddString(string s) { 
            if (s == null) {
                return;
            }
            if (attrValue != null) { 
                attrValue += s;
            } 
            else if (parent != null) { 
                parent.Add(s);
            } 
            else {
                Add(s);
            }
        } 
    }
 
    internal class XNodeReader : XmlReader, IXmlLineInfo 
    {
        // The reader position is encoded by the tuple (source, parent). 
        // Lazy text uses (instance, parent element). Attribute value
        // uses (instance, parent attribute). End element uses (instance,
        // instance). Common XObject uses (instance, null).
        object source; 
        object parent;
        ReadState state; 
        XNode root; 
        XmlNameTable nameTable;
 
        internal XNodeReader(XNode node, XmlNameTable nameTable) {
            this.source = node;
            this.root = node;
            this.nameTable = nameTable != null ? nameTable : CreateNameTable(); 
        }
 
        public override int AttributeCount { 
            get {
                if (!IsInteractive) { 
                    return 0;
                }
                int count = 0;
                XElement e = GetElementInAttributeScope(); 
                if (e != null) {
                    XAttribute a = e.lastAttr; 
                    if (a != null) { 
                        do {
                            a = a.next; 
                            count++;
                        } while (a != e.lastAttr);
                    }
                } 
                return count;
            } 
        } 

        public override string BaseURI { 
            get {
                if (!IsInteractive) {
                    return string.Empty;
                } 
                XObject o = source as XObject;
                if (o != null) { 
                    return o.BaseUri; 
                }
                o = parent as XObject; 
                if (o != null) {
                    return o.BaseUri;
                }
                return string.Empty; 
            }
        } 
 
        public override int Depth {
            get { 
                if (!IsInteractive) {
                    return 0;
                }
                XObject o = source as XObject; 
                if (o != null) {
                    return GetDepth(o); 
                } 
                o = parent as XObject;
                if (o != null) { 
                    return GetDepth(o) + 1;
                }
                return 0;
            } 
        }
 
        static int GetDepth(XObject o) { 
            int depth = 0;
            while (o.parent != null) { 
                depth++;
                o = o.parent;
            }
            if (o is XDocument) { 
                depth--;
            } 
            return depth; 
        }
 
        public override bool EOF {
            get { return state == ReadState.EndOfFile; }
        }
 
        public override bool HasAttributes {
            get { 
                if (!IsInteractive) { 
                    return false;
                } 
                XElement e = GetElementInAttributeScope();
                return e != null && e.lastAttr != null;
            }
        } 

        public override bool HasValue { 
            get { 
                if (!IsInteractive) {
                    return false; 
                }
                XObject o = source as XObject;
                if (o != null) {
                    switch (o.NodeType) { 
                        case XmlNodeType.Attribute:
                        case XmlNodeType.Text: 
                        case XmlNodeType.CDATA: 
                        case XmlNodeType.Comment:
                        case XmlNodeType.ProcessingInstruction: 
                        case XmlNodeType.DocumentType:
                            return true;
                        default:
                            return false; 
                    }
                } 
                return true; 
            }
        } 

        public override bool IsEmptyElement {
            get {
                if (!IsInteractive) { 
                    return false;
                } 
                XElement e = source as XElement; 
                return e != null && e.IsEmpty;
            } 
        }

        public override string LocalName {
            get { return nameTable.Add(GetLocalName()); } 
        }
 
        string GetLocalName() { 
            if (!IsInteractive) {
                return string.Empty; 
            }
            XElement e = source as XElement;
            if (e != null) {
                return e.Name.LocalName; 
            }
            XAttribute a = source as XAttribute; 
            if (a != null) { 
                return a.Name.LocalName;
            } 
            XProcessingInstruction p = source as XProcessingInstruction;
            if (p != null) {
                return p.Target;
            } 
            XDocumentType n = source as XDocumentType;
            if (n != null) { 
                return n.Name; 
            }
            return string.Empty; 
        }

        public override string Name {
            get { 
                string prefix = GetPrefix();
                if (prefix.Length == 0) { 
                    return nameTable.Add(GetLocalName()); 
                }
                return nameTable.Add(string.Concat(prefix, ":", GetLocalName())); 
            }
        }

        public override string NamespaceURI { 
            get { return nameTable.Add(GetNamespaceURI()); }
        } 
 
        string GetNamespaceURI() {
            if (!IsInteractive) { 
                return string.Empty;
            }
            XElement e = source as XElement;
            if (e != null) { 
                return e.Name.NamespaceName;
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                string namespaceName = a.Name.NamespaceName; 
                if (namespaceName.Length == 0 && a.Name.LocalName == "xmlns") {
                    return XNamespace.xmlnsPrefixNamespace;
                }
                return namespaceName; 
            }
            return string.Empty; 
        } 

        public override XmlNameTable NameTable { 
            get { return nameTable; }
        }

        public override XmlNodeType NodeType { 
            get {
                if (!IsInteractive) { 
                    return XmlNodeType.None; 
                }
                XObject o = source as XObject; 
                if (o != null) {
                    if (IsEndElement) {
                        return XmlNodeType.EndElement;
                    } 
                    XmlNodeType nt = o.NodeType;
                    if (nt != XmlNodeType.Text) { 
                        return nt; 
                    }
                    if (o.parent != null && o.parent.parent == null && o.parent is XDocument) { 
                        return XmlNodeType.Whitespace;
                    }
                    return XmlNodeType.Text;
                } 
                if (parent is XDocument) {
                    return XmlNodeType.Whitespace; 
                } 
                return XmlNodeType.Text;
            } 
        }

        public override string Prefix {
            get { return nameTable.Add(GetPrefix()); } 
        }
 
        string GetPrefix() { 
            if (!IsInteractive) {
                return string.Empty; 
            }
            XElement e = source as XElement;
            if (e != null) {
                string prefix = e.GetPrefixOfNamespace(e.Name.Namespace); 
                if (prefix != null) {
                    return prefix; 
                } 
                return string.Empty;
            } 
            XAttribute a = source as XAttribute;
            if (a != null) {
                string prefix = a.GetPrefixOfNamespace(a.Name.Namespace);
                if (prefix != null) { 
                    return prefix;
                } 
            } 
            return string.Empty;
        } 

        public override ReadState ReadState {
            get { return state; }
        } 

        public override XmlReaderSettings Settings { 
            get { 
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.CheckCharacters = false; 
                return settings;
            }
        }
 
        public override string Value {
            get { 
                if (!IsInteractive) { 
                    return string.Empty;
                } 
                XObject o = source as XObject;
                if (o != null) {
                    switch (o.NodeType) {
                        case XmlNodeType.Attribute: 
                            return ((XAttribute)o).Value;
                        case XmlNodeType.Text: 
                        case XmlNodeType.CDATA: 
                            return ((XText)o).Value;
                        case XmlNodeType.Comment: 
                            return ((XComment)o).Value;
                        case XmlNodeType.ProcessingInstruction:
                            return ((XProcessingInstruction)o).Data;
                        case XmlNodeType.DocumentType: 
                            return ((XDocumentType)o).InternalSubset;
                        default: 
                            return string.Empty; 
                    }
                } 
                return (string)source;
            }
        }
 
        public override string XmlLang {
            get { 
                if (!IsInteractive) { 
                    return string.Empty;
                } 
                XElement e = GetElementInScope();
                if (e != null) {
                    XName name = XNamespace.Xml.GetName("lang");
                    do { 
                        XAttribute a = e.Attribute(name);
                        if (a != null) { 
                            return a.Value; 
                        }
                        e = e.parent as XElement; 
                    } while (e != null);
                }
                return string.Empty;
            } 
        }
 
        public override XmlSpace XmlSpace { 
            get {
                if (!IsInteractive) { 
                    return XmlSpace.None;
                }
                XElement e = GetElementInScope();
                if (e != null) { 
                    XName name = XNamespace.Xml.GetName("space");
                    do { 
                        XAttribute a = e.Attribute(name); 
                        if (a != null) {
                            switch (a.Value.Trim(new char[] {' ', '\t', '\n', '\r'})) { 
                                case "preserve":
                                    return XmlSpace.Preserve;
                                case "default":
                                    return XmlSpace.Default; 
                                default:
                                    break; 
                            } 
                        }
                        e = e.parent as XElement; 
                    } while (e != null);
                }
                return XmlSpace.None;
            } 
        }
 
        public override void Close() { 
            source = null;
            parent = null; 
            root = null;
            state = ReadState.Closed;
        }
 
        public override string GetAttribute(string name) {
            if (!IsInteractive) { 
                return null; 
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                string localName, namespaceName;
                GetNameInAttributeScope(name, e, out localName, out namespaceName);
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do { 
                        a = a.next; 
                        if (a.Name.LocalName == localName && a.Name.NamespaceName == namespaceName) {
                            return a.Value; 
                        }
                    } while (a != e.lastAttr);
                }
                return null; 
            }
            XDocumentType n = source as XDocumentType; 
            if (n != null) { 
                switch (name) {
                    case "PUBLIC": 
                        return n.PublicId;
                    case "SYSTEM":
                        return n.SystemId;
                } 
            }
            return null; 
        } 

        public override string GetAttribute(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return null;
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                if (localName == "xmlns") { 
                    if (namespaceName != null && namespaceName.Length == 0) { 
                        return null;
                    } 
                    if (namespaceName == XNamespace.xmlnsPrefixNamespace) {
                        namespaceName = string.Empty;
                    }
                } 
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && a.Name.NamespaceName == namespaceName) { 
                            return a.Value;
                        }
                    } while (a != e.lastAttr);
                } 
            }
            return null; 
        } 

        public override string GetAttribute(int index) { 
            if (!IsInteractive) {
                return null;
            }
            if (index < 0) { 
                return null;
            } 
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                XAttribute a = e.lastAttr; 
                if (a != null) {
                    do {
                        a = a.next;
                        if (index-- == 0) { 
                            return a.Value;
                        } 
                    } while (a != e.lastAttr); 
                }
            } 
            return null;
        }

        public override string LookupNamespace(string prefix) { 
            if (!IsInteractive) {
                return null; 
            } 
            if (prefix == null) {
                return null; 
            }
            XElement e = GetElementInScope();
            if (e != null) {
                XNamespace ns = prefix.Length == 0 ? e.GetDefaultNamespace() : e.GetNamespaceOfPrefix(prefix); 
                if (ns != null) {
                    return nameTable.Add(ns.NamespaceName); 
                } 
            }
            return null; 
        }

        public override bool MoveToAttribute(string name) {
            if (!IsInteractive) { 
                return false;
            } 
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                string localName, namespaceName; 
                GetNameInAttributeScope(name, e, out localName, out namespaceName);
                XAttribute a = e.lastAttr;
                if (a != null) {
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && 
                            a.Name.NamespaceName == namespaceName) { 
                            source = a;
                            parent = null; 
                            return true;
                        }
                    } while (a != e.lastAttr);
                } 
            }
            return false; 
        } 

        public override bool MoveToAttribute(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return false;
            }
            XElement e = GetElementInAttributeScope(); 
            if (e != null) {
                if (localName == "xmlns") { 
                    if (namespaceName != null && namespaceName.Length == 0) { 
                        return false;
                    } 
                    if (namespaceName == XNamespace.xmlnsPrefixNamespace) {
                        namespaceName = string.Empty;
                    }
                } 
                XAttribute a = e.lastAttr;
                if (a != null) { 
                    do { 
                        a = a.next;
                        if (a.Name.LocalName == localName && 
                            a.Name.NamespaceName == namespaceName) {
                            source = a;
                            parent = null;
                            return true; 
                        }
                    } while (a != e.lastAttr); 
                } 
            }
            return false; 
        }

        public override void MoveToAttribute(int index) {
            if (!IsInteractive) { 
                return;
            } 
            if (index < 0) throw new ArgumentOutOfRangeException("index"); 
            XElement e = GetElementInAttributeScope();
            if (e != null) { 
                XAttribute a = e.lastAttr;
                if (a != null) {
                    do {
                        a = a.next; 
                        if (index-- == 0) {
                            source = a; 
                            parent = null; 
                            return;
                        } 
                    } while (a != e.lastAttr);
                }
            }
            throw new ArgumentOutOfRangeException("index"); 
        }
 
        public override bool MoveToElement() { 
            if (!IsInteractive) {
                return false; 
            }
            XAttribute a = source as XAttribute;
            if (a == null) {
                a = parent as XAttribute; 
            }
            if (a != null) { 
                if (a.parent != null) { 
                    source = a.parent;
                    parent = null; 
                    return true;
                }
            }
            return false; 
        }
 
        public override bool MoveToFirstAttribute() { 
            if (!IsInteractive) {
                return false; 
            }
            XElement e = GetElementInAttributeScope();
            if (e != null) {
                if (e.lastAttr != null) { 
                    source = e.lastAttr.next;
                    return true; 
                } 
            }
            return false; 
        }

        public override bool MoveToNextAttribute() {
            if (!IsInteractive) { 
                return false;
            } 
            XElement e = source as XElement; 
            if (e != null) {
                if (IsEndElement) { 
                    return false;
                }
                if (e.lastAttr != null) {
                    source = e.lastAttr.next; 
                    return true;
                } 
                return false; 
            }
            XAttribute a = source as XAttribute; 
            if (a == null) {
                a = parent as XAttribute;
            }
            if (a != null) { 
                if (a.parent != null && ((XElement)a.parent).lastAttr != a) {
                    source = a.next; 
                    parent = null; 
                    return true;
                } 
            }
            return false;
        }
 
        public override bool Read() {
            switch (state) { 
                case ReadState.Initial: 
                    state = ReadState.Interactive;
                    XDocument d = source as XDocument; 
                    if (d != null) {
                        return ReadIntoDocument(d);
                    }
                    return true; 
                case ReadState.Interactive:
                    return Read(false); 
                default: 
                    return false;
            } 
        }

        public override bool ReadAttributeValue() {
            if (!IsInteractive) { 
                return false;
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return ReadIntoAttribute(a); 
            }
            return false;
        }
 
        public override bool ReadToDescendant(string localName, string namespaceName) {
            if (!IsInteractive) { 
                return false; 
            }
            MoveToElement(); 
            XElement c = source as XElement;
            if (c != null && !c.IsEmpty) {
                if (IsEndElement) {
                    return false; 
                }
                foreach (XElement e in c.Descendants()) { 
                    if (e.Name.LocalName == localName && 
                        e.Name.NamespaceName == namespaceName) {
                        source = e; 
                        return true;
                    }
                }
                IsEndElement = true; 
            }
            return false; 
        } 

        public override bool ReadToFollowing(string localName, string namespaceName) { 
            while (Read()) {
                XElement e = source as XElement;
                if (e != null) {
                    if (IsEndElement) continue; 
                    if (e.Name.LocalName == localName && e.Name.NamespaceName == namespaceName) {
                        return true; 
                    } 
                }
            } 
            return false;
        }

        public override bool ReadToNextSibling(string localName, string namespaceName) { 
            if (!IsInteractive) {
                return false; 
            } 
            MoveToElement();
            if (source != root) { 
                XNode n = source as XNode;
                if (n != null) {
                    foreach (XElement e in n.ElementsAfterSelf()) {
                        if (e.Name.LocalName == localName && 
                            e.Name.NamespaceName == namespaceName) {
                            source = e; 
                            IsEndElement = false; 
                            return true;
                        } 
                    }
                    if (n.parent is XElement) {
                        source = n.parent;
                        IsEndElement = true; 
                        return false;
                    } 
                } 
                else {
                    if (parent is XElement) { 
                        source = parent;
                        parent = null;
                        IsEndElement = true;
                        return false; 
                    }
                } 
            } 
            return ReadToEnd();
        } 

        public override void ResolveEntity() {
        }
 
        public override void Skip() {
            if (!IsInteractive) { 
                return; 
            }
            Read(true); 
        }

        bool IXmlLineInfo.HasLineInfo() {
            IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo; 
            if (li != null) {
                return li.HasLineInfo(); 
            } 
            return false;
        } 

        int IXmlLineInfo.LineNumber {
            get {
                IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo; 
                if (li != null) {
                    return li.LineNumber; 
                } 
                return 0;
            } 
        }

        int IXmlLineInfo.LinePosition {
            get { 
                IXmlLineInfo li = IsEndElement ? null : source as IXmlLineInfo;
                if (li != null) { 
                    return li.LinePosition; 
                }
                return 0; 
            }
        }

        bool IsEndElement { 
            get { return parent == source; }
            set { parent = value ? source : null; } 
        } 

        bool IsInteractive { 
            get { return state == ReadState.Interactive; }
        }

        static XmlNameTable CreateNameTable() { 
            XmlNameTable nameTable = new NameTable();
            nameTable.Add(string.Empty); 
            nameTable.Add(XNamespace.xmlnsPrefixNamespace); 
            nameTable.Add(XNamespace.xmlPrefixNamespace);
            return nameTable; 
        }

        XElement GetElementInAttributeScope() {
            XElement e = source as XElement; 
            if (e != null) {
                if (IsEndElement) { 
                    return null; 
                }
                return e; 
            }
            XAttribute a = source as XAttribute;
            if (a != null) {
                return (XElement)a.parent; 
            }
            a = parent as XAttribute; 
            if (a != null) { 
                return (XElement)a.parent;
            } 
            return null;
        }

        XElement GetElementInScope() { 
            XElement e = source as XElement;
            if (e != null) { 
                return e; 
            }
            XNode n = source as XNode; 
            if (n != null) {
                return n.parent as XElement;
            }
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return (XElement)a.parent; 
            } 
            e = parent as XElement;
            if (e != null) { 
                return e;
            }
            a = parent as XAttribute;
            if (a != null) { 
                return (XElement)a.parent;
            } 
            return null; 
        }
 
        static void GetNameInAttributeScope(string qualifiedName, XElement e, out string localName, out string namespaceName) {
            if (qualifiedName != null && qualifiedName.Length != 0) {
                int i = qualifiedName.IndexOf(':');
                if (i != 0 && i != qualifiedName.Length - 1) { 
                    if (i == -1) {
                        localName = qualifiedName; 
                        namespaceName = string.Empty; 
                        return;
                    } 
                    XNamespace ns = e.GetNamespaceOfPrefix(qualifiedName.Substring(0, i));
                    if (ns != null) {
                        localName = qualifiedName.Substring(i + 1, qualifiedName.Length - i - 1);
                        namespaceName = ns.NamespaceName; 
                        return;
                    } 
                } 
            }
            localName = null; 
            namespaceName = null;
        }

        bool Read(bool skipContent) { 
            XElement e = source as XElement;
            if (e != null) { 
                if (e.IsEmpty || IsEndElement || skipContent) { 
                    return ReadOverNode(e);
                } 
                return ReadIntoElement(e);
            }
            XNode n = source as XNode;
            if (n != null) { 
                return ReadOverNode(n);
            } 
            XAttribute a = source as XAttribute; 
            if (a != null) {
                return ReadOverAttribute(a, skipContent); 
            }
            return ReadOverText(skipContent);
        }
 
        bool ReadIntoDocument(XDocument d) {
            XNode n = d.content as XNode; 
            if (n != null) { 
                source = n.next;
                return true; 
            }
            string s = d.content as string;
            if (s != null) {
                if (s.Length > 0) { 
                    source = s;
                    parent = d; 
                    return true; 
                }
            } 
            return ReadToEnd();
        }

        bool ReadIntoElement(XElement e) { 
            XNode n = e.content as XNode;
            if (n != null) { 
                source = n.next; 
                return true;
            } 
            string s = e.content as string;
            if (s != null) {
                if (s.Length > 0) {
                    source = s; 
                    parent = e;
                } 
                else { 
                    source = e;
                    IsEndElement = true; 
                }
                return true;
            }
            return ReadToEnd(); 
        }
 
        bool ReadIntoAttribute(XAttribute a) { 
            source = a.value;
            parent = a; 
            return true;
        }

        bool ReadOverAttribute(XAttribute a, bool skipContent) { 
            XElement e = (XElement)a.parent;
            if (e != null) { 
                if (e.IsEmpty || skipContent) { 
                    return ReadOverNode(e);
                } 
                return ReadIntoElement(e);
            }
            return ReadToEnd();
        } 

        bool ReadOverNode(XNode n) { 
            if (n == root) { 
                return ReadToEnd();
            } 
            XNode next = n.next;
            if (null == next || next == n || n == n.parent.content) {
                if (n.parent == null || (n.parent.parent == null && n.parent is XDocument)) {
                    return ReadToEnd(); 
                }
                source = n.parent; 
                IsEndElement = true; 
            }
            else { 
                source = next;
                IsEndElement = false;
            }
            return true; 
        }
 
        bool ReadOverText(bool skipContent) { 
            if (parent is XElement) {
                source = parent; 
                parent = null;
                IsEndElement = true;
                return true;
            } 
            if (parent is XAttribute) {
                XAttribute a = (XAttribute)parent; 
                parent = null; 
                return ReadOverAttribute(a, skipContent);
            } 
            return ReadToEnd();
        }

        bool ReadToEnd() { 
            state = ReadState.EndOfFile;
            return false; 
        } 
    }
 

#if !PRODUCTION_BUILD
    static class Res
    { 
        internal const string Argument_AddAttribute = "Argument_AddAttribute";
        internal const string Argument_AddNode = "Argument_AddNode"; 
        internal const string Argument_AddNonWhitespace = "Argument_AddNonWhitespace"; 
        internal const string Argument_ConvertToString = "Argument_ConvertToString";
        internal const string Argument_CreateNavigator = "Argument_CreateNavigator"; 
        internal const string Argument_InvalidExpandedName = "Argument_InvalidExpandedName";
        internal const string Argument_InvalidPIName = "Argument_InvalidPIName";
        internal const string Argument_InvalidPrefix = "Argument_InvalidPrefix";
        internal const string Argument_MustBeDerivedFrom = "Argument_MustBeDerivedFrom"; 
        internal const string Argument_NamespaceDeclarationPrefixed = "Argument_NamespaceDeclarationPrefixed";
        internal const string Argument_NamespaceDeclarationXml = "Argument_NamespaceDeclarationXml"; 
        internal const string Argument_NamespaceDeclarationXmlns = "Argument_NamespaceDeclarationXmlns"; 
        internal const string Argument_XObjectValue = "Argument_XObjectValue";
        internal const string InvalidOperation_BadNodeType = "InvalidOperation_BadNodeType"; 
        internal const string InvalidOperation_DocumentStructure = "InvalidOperation_DocumentStructure";
        internal const string InvalidOperation_DuplicateAttribute = "InvalidOperation_DuplicateAttribute";
        internal const string InvalidOperation_ExpectedEndOfFile = "InvalidOperation_ExpectedEndOfFile";
        internal const string InvalidOperation_ExpectedInteractive = "InvalidOperation_ExpectedInteractive"; 
        internal const string InvalidOperation_ExpectedNodeType = "InvalidOperation_ExpectedNodeType";
        internal const string InvalidOperation_ExternalCode = "InvalidOperation_ExternalCode"; 
        internal const string InvalidOperation_DeserializeInstance = "InvalidOperation_DeserializeInstance"; 
        internal const string InvalidOperation_MissingAncestor = "InvalidOperation_MissingAncestor";
        internal const string InvalidOperation_MissingParent = "InvalidOperation_MissingParent"; 
        internal const string InvalidOperation_MissingRoot = "InvalidOperation_MissingRoot";
        internal const string InvalidOperation_UnexpectedEvaluation = "InvalidOperation_UnexpectedEvaluation";
        internal const string InvalidOperation_UnexpectedNodeType = "InvalidOperation_UnexpectedNodeType";
        internal const string InvalidOperation_UnresolvedEntityReference = "InvalidOperation_UnresolvedEntityReference"; 
        internal const string InvalidOperation_WriteAttribute = "InvalidOperation_WriteAttribute";
        internal const string NotSupported_CheckValidity = "NotSupported_CheckValidity"; 
        internal const string NotSupported_MoveToId = "NotSupported_MoveToId"; 
        internal const string NotSupported_WriteBase64 = "NotSupported_WriteBase64";
        internal const string NotSupported_WriteEntityRef = "NotSupported_WriteEntityRef"; 

        public static string GetString(string name) {
            switch (name) {
                case Argument_AddAttribute: 
                    return "An attribute cannot be added to content.";
                case Argument_AddNode: 
                    return "A node of type {0} cannot be added to content."; 
                case Argument_AddNonWhitespace:
                    return "Non white space characters cannot be added to content."; 
                case Argument_ConvertToString:
                    return "The argument cannot be converted to a string.";
                case Argument_CreateNavigator:
                    return "This XPathNavigator cannot be created on a node of type {0}."; 
                case Argument_InvalidExpandedName:
                    return "'{0}' is an invalid expanded name."; 
                case Argument_InvalidPIName: 
                    return "'{0}' is an invalid name for a processing instruction.";
                case Argument_InvalidPrefix: 
                    return "'{0}' is an invalid prefix.";
                case Argument_MustBeDerivedFrom:
                    return "The argument must be derived from {0}.";
                case Argument_NamespaceDeclarationPrefixed: 
                     return "The prefix '{0}' cannot be bound to the empty namespace name.";
                case Argument_NamespaceDeclarationXml: 
                     return "The prefix 'xml' is bound to the namespace name 'http://www.w3.org/XML/1998/namespace'. Other prefixes must not be bound to this namespace name, and it must not be declared as the default namespace."; 
                case Argument_NamespaceDeclarationXmlns:
                     return "The prefix 'xmlns' is bound to the namespace name 'http://www.w3.org/2000/xmlns/'. It must not be declared. Other prefixes must not be bound to this namespace name, and it must not be declared as the default namespace."; 
                case Argument_XObjectValue:
                    return "An XObject cannot be used as a value.";
                case InvalidOperation_BadNodeType:
                    return "This operation is not valid on a node of type {0}."; 
                case InvalidOperation_DocumentStructure:
                    return "This operation would create an incorrectly structured document."; 
                case InvalidOperation_DuplicateAttribute: 
                    return "Duplicate attribute.";
                case InvalidOperation_ExpectedEndOfFile: 
                    return "The XmlReader state should be EndOfFile after this operation.";
                case InvalidOperation_ExpectedInteractive:
                    return "The XmlReader state should be Interactive.";
                case InvalidOperation_ExpectedNodeType: 
                    return "The XmlReader must be on a node of type {0} instead of a node of type {1}.";
                case InvalidOperation_ExternalCode: 
                    return "This operation was corrupted by external code."; 
                case InvalidOperation_DeserializeInstance:
                    return "This instance cannot be deserialized."; 
                case InvalidOperation_MissingAncestor:
                    return "A common ancestor is missing.";
                case InvalidOperation_MissingParent:
                    return "The parent is missing."; 
                case InvalidOperation_MissingRoot:
                    return "The root element is missing."; 
                case InvalidOperation_UnexpectedEvaluation: 
                    return "The XPath expression evaluated to unexpected type {0}.";
                case InvalidOperation_UnexpectedNodeType: 
                    return "The XmlReader should not be on a node of type {0}.";
                case InvalidOperation_UnresolvedEntityReference:
                    return "The XmlReader cannot resolve entity references.";
                case InvalidOperation_WriteAttribute: 
                    return "An attribute cannot be written after content.";
                case NotSupported_CheckValidity: 
                    return "This XPathNavigator does not support XSD validation."; 
                case NotSupported_MoveToId:
                    return "This XPathNavigator does not support IDs."; 
                case NotSupported_WriteBase64:
                    return "This XmlWriter does not support base64 encoded data.";
                case NotSupported_WriteEntityRef:
                    return "This XmlWriter does not support entity references."; 
            }
            return null; 
        } 

        public static string GetString(string name, params object[] args) { 
            string res = GetString(name);
            if (args == null || args.Length == 0) return res;
            return string.Format(CultureInfo.CurrentCulture, res, args);
        } 
    }
#endif 
} 

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