Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Xml / System / Xml / Dom / XmlElementList.cs / 1 / 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 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; new XmlElementListListener(parent.Document, this); } 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 ) { XmlElementList elemList = (XmlElementList)this.elemList.Target; if (null != elemList) { elemList.ConcurrencyCheck(args); } else { this.doc.NodeInserted -= this.nodeChangeHandler; this.doc.NodeRemoved -= this.nodeChangeHandler; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridViewAutoSizeModeEventArgs.cs
- CatalogZone.cs
- WorkflowDefinitionContext.cs
- ExeConfigurationFileMap.cs
- Size.cs
- Encoder.cs
- StandardToolWindows.cs
- InstanceData.cs
- ApplicationCommands.cs
- TreeView.cs
- CompatibleComparer.cs
- SHA256Managed.cs
- ScalarConstant.cs
- RowUpdatedEventArgs.cs
- Activator.cs
- MasterPageParser.cs
- FrameworkTextComposition.cs
- Completion.cs
- XhtmlBasicPageAdapter.cs
- BoundColumn.cs
- Convert.cs
- LicenseException.cs
- ResourceFallbackManager.cs
- XmlComment.cs
- X500Name.cs
- smtppermission.cs
- MSAAWinEventWrap.cs
- ToolStripSettings.cs
- PeerTransportListenAddressValidator.cs
- File.cs
- IsolatedStorage.cs
- SequenceQuery.cs
- EventData.cs
- SqlXml.cs
- DefaultAssemblyResolver.cs
- documentsequencetextpointer.cs
- ClientCultureInfo.cs
- CornerRadiusConverter.cs
- ItemList.cs
- RuntimeHandles.cs
- PresentationAppDomainManager.cs
- XmlSerializableWriter.cs
- FileInfo.cs
- D3DImage.cs
- EditCommandColumn.cs
- GlyphTypeface.cs
- XmlReader.cs
- CursorConverter.cs
- SoapIncludeAttribute.cs
- WindowsFormsSynchronizationContext.cs
- ASCIIEncoding.cs
- DataBoundControl.cs
- Control.cs
- ISCIIEncoding.cs
- ModuleConfigurationInfo.cs
- ListViewHitTestInfo.cs
- ObjectStateManager.cs
- RightsManagementEncryptedStream.cs
- SqlServices.cs
- CornerRadius.cs
- ItemsPresenter.cs
- CompoundFileStorageReference.cs
- CodeConstructor.cs
- SqlConnectionFactory.cs
- MdImport.cs
- DataGridViewHitTestInfo.cs
- RightNameExpirationInfoPair.cs
- SelectionBorderGlyph.cs
- ResourceDictionaryCollection.cs
- ResourcesChangeInfo.cs
- ConstraintStruct.cs
- String.cs
- ProgressBarRenderer.cs
- mongolianshape.cs
- TdsParameterSetter.cs
- SqlLiftWhereClauses.cs
- DetailsViewDeleteEventArgs.cs
- OleDbCommandBuilder.cs
- XmlNavigatorStack.cs
- RecommendedAsConfigurableAttribute.cs
- MimePart.cs
- DelegateHelpers.Generated.cs
- BitmapImage.cs
- ResolveMatchesApril2005.cs
- RSAPKCS1SignatureFormatter.cs
- TextEditorDragDrop.cs
- _ListenerRequestStream.cs
- ArcSegment.cs
- TypefaceMetricsCache.cs
- DataGridPreparingCellForEditEventArgs.cs
- HttpCookieCollection.cs
- CanonicalXml.cs
- _ListenerAsyncResult.cs
- WebBrowserDocumentCompletedEventHandler.cs
- NativeMethods.cs
- TextComposition.cs
- LightweightEntityWrapper.cs
- ShapingWorkspace.cs
- DesignerOptionService.cs
- RepeaterItemCollection.cs