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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CountdownEvent.cs
- HtmlObjectListAdapter.cs
- BamlLocalizationDictionary.cs
- SystemWebCachingSectionGroup.cs
- State.cs
- SystemColorTracker.cs
- BitmapData.cs
- Activator.cs
- LowerCaseStringConverter.cs
- ConfigXmlCDataSection.cs
- EventProxy.cs
- BidOverLoads.cs
- Scene3D.cs
- SoapUnknownHeader.cs
- LogManagementAsyncResult.cs
- SmtpException.cs
- CustomLineCap.cs
- ReadOnlyNameValueCollection.cs
- NavigationPropertyEmitter.cs
- SqlTransaction.cs
- _AutoWebProxyScriptEngine.cs
- RegistrationServices.cs
- MenuEventArgs.cs
- PingReply.cs
- BinaryMethodMessage.cs
- WebPartDisplayModeEventArgs.cs
- ExpressionUtilities.cs
- RewritingSimplifier.cs
- NeutralResourcesLanguageAttribute.cs
- LinearQuaternionKeyFrame.cs
- SafeEventLogWriteHandle.cs
- InputLanguageCollection.cs
- ImpersonationContext.cs
- ServiceModelConfigurationSection.cs
- HostedTcpTransportManager.cs
- WebServiceData.cs
- Rect.cs
- SafeRightsManagementSessionHandle.cs
- PerformanceCounterPermission.cs
- SequenceRange.cs
- TemplateKeyConverter.cs
- initElementDictionary.cs
- SpinLock.cs
- ISAPIRuntime.cs
- _SafeNetHandles.cs
- ResourceDictionary.cs
- SqlDelegatedTransaction.cs
- WebDescriptionAttribute.cs
- smtppermission.cs
- KerberosReceiverSecurityToken.cs
- WinFormsUtils.cs
- EmptyControlCollection.cs
- HttpChannelListener.cs
- CommandDevice.cs
- BaseProcessProtocolHandler.cs
- PersonalizationStateQuery.cs
- CodeObjectCreateExpression.cs
- XMLDiffLoader.cs
- SrgsDocumentParser.cs
- PriorityQueue.cs
- AppDomain.cs
- XmlSchemaSimpleTypeRestriction.cs
- TextWriterEngine.cs
- TextBox.cs
- OrderedHashRepartitionEnumerator.cs
- CertificateManager.cs
- KeyManager.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- NestedContainer.cs
- DocumentationServerProtocol.cs
- IdentitySection.cs
- RowsCopiedEventArgs.cs
- BinaryObjectInfo.cs
- SingleStorage.cs
- CodeSnippetCompileUnit.cs
- GrammarBuilderDictation.cs
- RenderData.cs
- FactoryMaker.cs
- _Connection.cs
- NavigationProgressEventArgs.cs
- CompilerTypeWithParams.cs
- WebPartMenu.cs
- FigureParaClient.cs
- HotSpot.cs
- ParentUndoUnit.cs
- BitmapImage.cs
- ImageIndexEditor.cs
- XmlSignatureManifest.cs
- CompilerTypeWithParams.cs
- BrowsableAttribute.cs
- ResXFileRef.cs
- XamlToRtfParser.cs
- DbReferenceCollection.cs
- MimeTypeMapper.cs
- ConsumerConnectionPoint.cs
- SourceSwitch.cs
- ServiceNotStartedException.cs
- ResourceWriter.cs
- DesignerHierarchicalDataSourceView.cs
- ImageFormatConverter.cs