Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Dom / XmlElementList.cs / 1305376 / XmlElementList.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml { using System; using System.Collections; using System.Diagnostics; internal class XmlElementList: XmlNodeList { string asterisk; int changeCount; //recording the total number that the dom tree has been changed ( insertion and deletetion ) //the member vars below are saved for further reconstruction string name; //only one of 2 string groups will be initialized depends on which constructor is called. string localName; string namespaceURI; XmlNode rootNode; // the memeber vars belwo serves the optimization of accessing of the elements in the list int curInd; // -1 means the starting point for a new search round XmlNode curElem; // if sets to rootNode, means the starting point for a new search round bool empty; // whether the list is empty bool atomized; //whether the localname and namespaceuri are aomized int matchCount; // cached list count. -1 means it needs reconstruction XmlElementListListener listener; private XmlElementList( XmlNode parent) { Debug.Assert ( parent != null ); Debug.Assert( parent.NodeType == XmlNodeType.Element || parent.NodeType == XmlNodeType.Document ); this.rootNode = parent; Debug.Assert( parent.Document != null ); this.curInd = -1; this.curElem = rootNode; this.changeCount = 0; this.empty = false; this.atomized = true; this.matchCount = -1; listener = new XmlElementListListener(parent.Document, this); } ~XmlElementList() { if ( listener != null ) { listener.Unregister(); listener = null; } } internal void ConcurrencyCheck(XmlNodeChangedEventArgs args){ if( atomized == false ) { XmlNameTable nameTable = this.rootNode.Document.NameTable; this.localName = nameTable.Add( this.localName ); this.namespaceURI = nameTable.Add( this.namespaceURI ); this.atomized = true; } if ( IsMatch( args.Node ) ) { this.changeCount++ ; this.curInd = -1; this.curElem = rootNode; if( args.Action == XmlNodeChangedAction.Insert ) this.empty = false; } this.matchCount = -1; } internal XmlElementList( XmlNode parent, string name ): this( parent ) { Debug.Assert( parent.Document != null ); XmlNameTable nt = parent.Document.NameTable; Debug.Assert( nt != null ); asterisk = nt.Add("*"); this.name = nt.Add( name ); this.localName = null; this.namespaceURI = null; } internal XmlElementList( XmlNode parent, string localName, string namespaceURI ): this( parent ) { Debug.Assert( parent.Document != null ); XmlNameTable nt = parent.Document.NameTable; Debug.Assert( nt != null ); asterisk = nt.Add("*"); this.localName = nt.Get( localName ); this.namespaceURI = nt.Get( namespaceURI ); if( (this.localName == null) || (this.namespaceURI== null) ) { this.empty = true; this.atomized = false; this.localName = localName; this.namespaceURI = namespaceURI; } this.name = null; } internal int ChangeCount { get { return changeCount; } } // return the next element node that is in PreOrder private XmlNode NextElemInPreOrder( XmlNode curNode ) { Debug.Assert( curNode != null ); //For preorder walking, first try its child XmlNode retNode = curNode.FirstChild; if ( retNode == null ) { //if no child, the next node forward will the be the NextSibling of the first ancestor which has NextSibling //so, first while-loop find out such an ancestor (until no more ancestor or the ancestor is the rootNode retNode = curNode; while ( retNode != null && retNode != rootNode && retNode.NextSibling == null ) { retNode = retNode.ParentNode; } //then if such ancestor exists, set the retNode to its NextSibling if ( retNode != null && retNode != rootNode ) retNode = retNode.NextSibling; } if ( retNode == this.rootNode ) //if reach the rootNode, consider having walked through the whole tree and no more element after the curNode retNode = null; return retNode; } // return the previous element node that is in PreOrder private XmlNode PrevElemInPreOrder( XmlNode curNode ) { Debug.Assert( curNode != null ); //For preorder walking, the previous node will be the right-most node in the tree of PreviousSibling of the curNode XmlNode retNode = curNode.PreviousSibling; // so if the PreviousSibling is not null, going through the tree down to find the right-most node while ( retNode != null ) { if ( retNode.LastChild == null ) break; retNode = retNode.LastChild; } // if no PreviousSibling, the previous node will be the curNode's parentNode if ( retNode == null ) retNode = curNode.ParentNode; // if the final retNode is rootNode, consider having walked through the tree and no more previous node if ( retNode == this.rootNode ) retNode = null; return retNode; } // if the current node a matching element node private bool IsMatch ( XmlNode curNode ) { if (curNode.NodeType == XmlNodeType.Element) { if ( this.name != null ) { if ( Ref.Equal(this.name, asterisk) || Ref.Equal(curNode.Name, this.name) ) return true; } else { if ( (Ref.Equal(this.localName, asterisk) || Ref.Equal(curNode.LocalName, this.localName) ) && (Ref.Equal(this.namespaceURI, asterisk) || curNode.NamespaceURI == this.namespaceURI ) ) { return true; } } } return false; } private XmlNode GetMatchingNode( XmlNode n, bool bNext ) { Debug.Assert( n!= null ); XmlNode node = n; do { if ( bNext ) node = NextElemInPreOrder( node ); else node = PrevElemInPreOrder( node ); } while ( node != null && !IsMatch( node ) ); return node; } private XmlNode GetNthMatchingNode( XmlNode n, bool bNext, int nCount ) { Debug.Assert( n!= null ); XmlNode node = n; for ( int ind = 0 ; ind < nCount; ind++ ) { node = GetMatchingNode( node, bNext ); if ( node == null ) return null; } return node; } //the function is for the enumerator to find out the next available matching element node public XmlNode GetNextNode( XmlNode n ) { if( this.empty == true ) return null; XmlNode node = ( n == null ) ? rootNode : n; return GetMatchingNode( node, true ); } public override XmlNode Item(int index) { if ( rootNode == null || index < 0 ) return null; if( this.empty == true ) return null; if ( curInd == index ) return curElem; int nDiff = index - curInd; bool bForward = ( nDiff > 0 ); if ( nDiff < 0 ) nDiff = -nDiff; XmlNode node; if ( ( node = GetNthMatchingNode( curElem, bForward, nDiff ) ) != null ) { curInd = index; curElem = node; return curElem; } return null; } public override int Count { get { if( this.empty == true ) return 0; if (this.matchCount < 0) { int currMatchCount = 0; int currChangeCount = this.changeCount; XmlNode node = rootNode; while ((node = GetMatchingNode(node, true)) != null) { currMatchCount++; } if (currChangeCount != this.changeCount) { return currMatchCount; } this.matchCount = currMatchCount; } return this.matchCount; } } public override IEnumerator GetEnumerator() { if( this.empty == true ) return new XmlEmptyElementListEnumerator(this);; return new XmlElementListEnumerator(this); } } internal class XmlElementListEnumerator : IEnumerator { XmlElementList list; XmlNode curElem; int changeCount; //save the total number that the dom tree has been changed ( insertion and deletetion ) when this enumerator is created public XmlElementListEnumerator( XmlElementList list ) { this.list = list; this.curElem = null; this.changeCount = list.ChangeCount; } public bool MoveNext() { if ( list.ChangeCount != this.changeCount ) { //the number mismatch, there is new change(s) happened since last MoveNext() is called. throw new InvalidOperationException( Res.GetString(Res.Xdom_Enum_ElementList) ); } else { curElem = list.GetNextNode( curElem ); } return curElem != null; } public void Reset() { curElem = null; //reset the number of changes to be synced with current dom tree as well this.changeCount = list.ChangeCount; } public object Current { get { return curElem; } } } internal class XmlEmptyElementListEnumerator : IEnumerator { public XmlEmptyElementListEnumerator( XmlElementList list ) { } public bool MoveNext() { return false; } public void Reset() { } public object Current { get { return null; } } } internal class XmlElementListListener { WeakReference elemList; XmlDocument doc; XmlNodeChangedEventHandler nodeChangeHandler = null; internal XmlElementListListener(XmlDocument doc, XmlElementList elemList) { this.doc = doc; this.elemList = new WeakReference(elemList); this.nodeChangeHandler = new XmlNodeChangedEventHandler( this.OnListChanged ); doc.NodeInserted += this.nodeChangeHandler; doc.NodeRemoved += this.nodeChangeHandler; } private void OnListChanged( object sender, XmlNodeChangedEventArgs args ) { lock (this) { if (this.elemList != null) { XmlElementList el = (XmlElementList)this.elemList.Target; if (null != el) { el.ConcurrencyCheck(args); } else { this.doc.NodeInserted -= this.nodeChangeHandler; this.doc.NodeRemoved -= this.nodeChangeHandler; this.elemList = null; } } } } // This method is called from the finalizer of XmlElementList internal void Unregister() { lock (this) { if (elemList != null) { this.doc.NodeInserted -= this.nodeChangeHandler; this.doc.NodeRemoved -= this.nodeChangeHandler; this.elemList = null; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml { using System; using System.Collections; using System.Diagnostics; internal class XmlElementList: XmlNodeList { string asterisk; int changeCount; //recording the total number that the dom tree has been changed ( insertion and deletetion ) //the member vars below are saved for further reconstruction string name; //only one of 2 string groups will be initialized depends on which constructor is called. string localName; string namespaceURI; XmlNode rootNode; // the memeber vars belwo serves the optimization of accessing of the elements in the list int curInd; // -1 means the starting point for a new search round XmlNode curElem; // if sets to rootNode, means the starting point for a new search round bool empty; // whether the list is empty bool atomized; //whether the localname and namespaceuri are aomized int matchCount; // cached list count. -1 means it needs reconstruction XmlElementListListener listener; private XmlElementList( XmlNode parent) { Debug.Assert ( parent != null ); Debug.Assert( parent.NodeType == XmlNodeType.Element || parent.NodeType == XmlNodeType.Document ); this.rootNode = parent; Debug.Assert( parent.Document != null ); this.curInd = -1; this.curElem = rootNode; this.changeCount = 0; this.empty = false; this.atomized = true; this.matchCount = -1; listener = new XmlElementListListener(parent.Document, this); } ~XmlElementList() { if ( listener != null ) { listener.Unregister(); listener = null; } } internal void ConcurrencyCheck(XmlNodeChangedEventArgs args){ if( atomized == false ) { XmlNameTable nameTable = this.rootNode.Document.NameTable; this.localName = nameTable.Add( this.localName ); this.namespaceURI = nameTable.Add( this.namespaceURI ); this.atomized = true; } if ( IsMatch( args.Node ) ) { this.changeCount++ ; this.curInd = -1; this.curElem = rootNode; if( args.Action == XmlNodeChangedAction.Insert ) this.empty = false; } this.matchCount = -1; } internal XmlElementList( XmlNode parent, string name ): this( parent ) { Debug.Assert( parent.Document != null ); XmlNameTable nt = parent.Document.NameTable; Debug.Assert( nt != null ); asterisk = nt.Add("*"); this.name = nt.Add( name ); this.localName = null; this.namespaceURI = null; } internal XmlElementList( XmlNode parent, string localName, string namespaceURI ): this( parent ) { Debug.Assert( parent.Document != null ); XmlNameTable nt = parent.Document.NameTable; Debug.Assert( nt != null ); asterisk = nt.Add("*"); this.localName = nt.Get( localName ); this.namespaceURI = nt.Get( namespaceURI ); if( (this.localName == null) || (this.namespaceURI== null) ) { this.empty = true; this.atomized = false; this.localName = localName; this.namespaceURI = namespaceURI; } this.name = null; } internal int ChangeCount { get { return changeCount; } } // return the next element node that is in PreOrder private XmlNode NextElemInPreOrder( XmlNode curNode ) { Debug.Assert( curNode != null ); //For preorder walking, first try its child XmlNode retNode = curNode.FirstChild; if ( retNode == null ) { //if no child, the next node forward will the be the NextSibling of the first ancestor which has NextSibling //so, first while-loop find out such an ancestor (until no more ancestor or the ancestor is the rootNode retNode = curNode; while ( retNode != null && retNode != rootNode && retNode.NextSibling == null ) { retNode = retNode.ParentNode; } //then if such ancestor exists, set the retNode to its NextSibling if ( retNode != null && retNode != rootNode ) retNode = retNode.NextSibling; } if ( retNode == this.rootNode ) //if reach the rootNode, consider having walked through the whole tree and no more element after the curNode retNode = null; return retNode; } // return the previous element node that is in PreOrder private XmlNode PrevElemInPreOrder( XmlNode curNode ) { Debug.Assert( curNode != null ); //For preorder walking, the previous node will be the right-most node in the tree of PreviousSibling of the curNode XmlNode retNode = curNode.PreviousSibling; // so if the PreviousSibling is not null, going through the tree down to find the right-most node while ( retNode != null ) { if ( retNode.LastChild == null ) break; retNode = retNode.LastChild; } // if no PreviousSibling, the previous node will be the curNode's parentNode if ( retNode == null ) retNode = curNode.ParentNode; // if the final retNode is rootNode, consider having walked through the tree and no more previous node if ( retNode == this.rootNode ) retNode = null; return retNode; } // if the current node a matching element node private bool IsMatch ( XmlNode curNode ) { if (curNode.NodeType == XmlNodeType.Element) { if ( this.name != null ) { if ( Ref.Equal(this.name, asterisk) || Ref.Equal(curNode.Name, this.name) ) return true; } else { if ( (Ref.Equal(this.localName, asterisk) || Ref.Equal(curNode.LocalName, this.localName) ) && (Ref.Equal(this.namespaceURI, asterisk) || curNode.NamespaceURI == this.namespaceURI ) ) { return true; } } } return false; } private XmlNode GetMatchingNode( XmlNode n, bool bNext ) { Debug.Assert( n!= null ); XmlNode node = n; do { if ( bNext ) node = NextElemInPreOrder( node ); else node = PrevElemInPreOrder( node ); } while ( node != null && !IsMatch( node ) ); return node; } private XmlNode GetNthMatchingNode( XmlNode n, bool bNext, int nCount ) { Debug.Assert( n!= null ); XmlNode node = n; for ( int ind = 0 ; ind < nCount; ind++ ) { node = GetMatchingNode( node, bNext ); if ( node == null ) return null; } return node; } //the function is for the enumerator to find out the next available matching element node public XmlNode GetNextNode( XmlNode n ) { if( this.empty == true ) return null; XmlNode node = ( n == null ) ? rootNode : n; return GetMatchingNode( node, true ); } public override XmlNode Item(int index) { if ( rootNode == null || index < 0 ) return null; if( this.empty == true ) return null; if ( curInd == index ) return curElem; int nDiff = index - curInd; bool bForward = ( nDiff > 0 ); if ( nDiff < 0 ) nDiff = -nDiff; XmlNode node; if ( ( node = GetNthMatchingNode( curElem, bForward, nDiff ) ) != null ) { curInd = index; curElem = node; return curElem; } return null; } public override int Count { get { if( this.empty == true ) return 0; if (this.matchCount < 0) { int currMatchCount = 0; int currChangeCount = this.changeCount; XmlNode node = rootNode; while ((node = GetMatchingNode(node, true)) != null) { currMatchCount++; } if (currChangeCount != this.changeCount) { return currMatchCount; } this.matchCount = currMatchCount; } return this.matchCount; } } public override IEnumerator GetEnumerator() { if( this.empty == true ) return new XmlEmptyElementListEnumerator(this);; return new XmlElementListEnumerator(this); } } internal class XmlElementListEnumerator : IEnumerator { XmlElementList list; XmlNode curElem; int changeCount; //save the total number that the dom tree has been changed ( insertion and deletetion ) when this enumerator is created public XmlElementListEnumerator( XmlElementList list ) { this.list = list; this.curElem = null; this.changeCount = list.ChangeCount; } public bool MoveNext() { if ( list.ChangeCount != this.changeCount ) { //the number mismatch, there is new change(s) happened since last MoveNext() is called. throw new InvalidOperationException( Res.GetString(Res.Xdom_Enum_ElementList) ); } else { curElem = list.GetNextNode( curElem ); } return curElem != null; } public void Reset() { curElem = null; //reset the number of changes to be synced with current dom tree as well this.changeCount = list.ChangeCount; } public object Current { get { return curElem; } } } internal class XmlEmptyElementListEnumerator : IEnumerator { public XmlEmptyElementListEnumerator( XmlElementList list ) { } public bool MoveNext() { return false; } public void Reset() { } public object Current { get { return null; } } } internal class XmlElementListListener { WeakReference elemList; XmlDocument doc; XmlNodeChangedEventHandler nodeChangeHandler = null; internal XmlElementListListener(XmlDocument doc, XmlElementList elemList) { this.doc = doc; this.elemList = new WeakReference(elemList); this.nodeChangeHandler = new XmlNodeChangedEventHandler( this.OnListChanged ); doc.NodeInserted += this.nodeChangeHandler; doc.NodeRemoved += this.nodeChangeHandler; } private void OnListChanged( object sender, XmlNodeChangedEventArgs args ) { lock (this) { if (this.elemList != null) { XmlElementList el = (XmlElementList)this.elemList.Target; if (null != el) { el.ConcurrencyCheck(args); } else { this.doc.NodeInserted -= this.nodeChangeHandler; this.doc.NodeRemoved -= this.nodeChangeHandler; this.elemList = null; } } } } // This method is called from the finalizer of XmlElementList internal void Unregister() { lock (this) { if (elemList != null) { this.doc.NodeInserted -= this.nodeChangeHandler; this.doc.NodeRemoved -= this.nodeChangeHandler; this.elemList = null; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
![Network programming in C#, Network Programming in VB.NET, Network Programming in .NET](/images/book.jpg)
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RegexReplacement.cs
- MarshalByRefObject.cs
- ConditionalWeakTable.cs
- InternalResources.cs
- DetailsViewCommandEventArgs.cs
- CriticalFileToken.cs
- SQLDouble.cs
- MorphHelper.cs
- TableLayoutStyle.cs
- VerticalAlignConverter.cs
- SecurityTokenAuthenticator.cs
- METAHEADER.cs
- SqlNamer.cs
- ConfigurationSectionCollection.cs
- RadioButtonList.cs
- PageRequestManager.cs
- SqlConnectionStringBuilder.cs
- ProcessHostConfigUtils.cs
- TimeStampChecker.cs
- GatewayIPAddressInformationCollection.cs
- BitmapData.cs
- localization.cs
- DnsElement.cs
- InputLangChangeEvent.cs
- DefaultPropertyAttribute.cs
- CacheVirtualItemsEvent.cs
- HitTestWithPointDrawingContextWalker.cs
- ReadOnlyDictionary.cs
- MappingException.cs
- SecurityDocument.cs
- InternalTypeHelper.cs
- ActivityTypeDesigner.xaml.cs
- DbConnectionClosed.cs
- XmlSchema.cs
- SecurityPermission.cs
- ColorAnimation.cs
- CryptoHelper.cs
- MailDefinition.cs
- ObjectPropertyMapping.cs
- WindowsRebar.cs
- FirstMatchCodeGroup.cs
- EditorServiceContext.cs
- D3DImage.cs
- HtmlEmptyTagControlBuilder.cs
- DataTableExtensions.cs
- DBCSCodePageEncoding.cs
- CodeAttributeDeclaration.cs
- XmlImplementation.cs
- IisTraceListener.cs
- QueryStringParameter.cs
- ResourcePool.cs
- Profiler.cs
- DataGridRowClipboardEventArgs.cs
- InputLangChangeEvent.cs
- XmlConvert.cs
- Rotation3DAnimationBase.cs
- GridViewItemAutomationPeer.cs
- XmlSchemaNotation.cs
- _Semaphore.cs
- LinqDataView.cs
- SoundPlayer.cs
- SelectedCellsChangedEventArgs.cs
- IApplicationTrustManager.cs
- TextEmbeddedObject.cs
- ByteStack.cs
- ListMarkerSourceInfo.cs
- BrowserCapabilitiesCodeGenerator.cs
- NamespaceTable.cs
- SQLInt32Storage.cs
- SessionStateModule.cs
- MimeBasePart.cs
- ImageSourceConverter.cs
- ReadOnlyDataSource.cs
- GorillaCodec.cs
- UnsafeNativeMethods.cs
- XmlSchemaComplexType.cs
- PingReply.cs
- DuplexSecurityProtocolFactory.cs
- ArrayConverter.cs
- DataBinding.cs
- FocusManager.cs
- EpmCustomContentSerializer.cs
- FreeFormDesigner.cs
- ExternalException.cs
- DataGridViewColumnCollection.cs
- Dictionary.cs
- CrossContextChannel.cs
- RequestCache.cs
- SharedPersonalizationStateInfo.cs
- PageFunction.cs
- XmlnsCache.cs
- NameHandler.cs
- PageAsyncTask.cs
- SolidColorBrush.cs
- HtmlLink.cs
- NavigationService.cs
- MethodBody.cs
- TagNameToTypeMapper.cs
- StreamSecurityUpgradeInitiator.cs
- DocumentViewerHelper.cs