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
- SystemIPAddressInformation.cs
- SecurityKeyIdentifierClause.cs
- elementinformation.cs
- EventSetterHandlerConverter.cs
- ClientConfigurationSystem.cs
- KeySplineConverter.cs
- WebPartEditorApplyVerb.cs
- DocumentViewerHelper.cs
- AssemblyNameProxy.cs
- ServiceNameCollection.cs
- _SslState.cs
- BookmarkScopeInfo.cs
- CornerRadius.cs
- GeneralTransform3D.cs
- Accessible.cs
- ListViewSortEventArgs.cs
- WmlValidationSummaryAdapter.cs
- DockPanel.cs
- XXXOnTypeBuilderInstantiation.cs
- XamlVector3DCollectionSerializer.cs
- VersionPair.cs
- TraceHandlerErrorFormatter.cs
- ButtonRenderer.cs
- ThemeInfoAttribute.cs
- ChannelManager.cs
- RowVisual.cs
- RNGCryptoServiceProvider.cs
- ZeroOpNode.cs
- QuaternionConverter.cs
- PropertyGridEditorPart.cs
- AspNetHostingPermission.cs
- DataGridHeaderBorder.cs
- EncoderExceptionFallback.cs
- PartitionedStream.cs
- PostBackOptions.cs
- Environment.cs
- FreezableCollection.cs
- StringStorage.cs
- Transform3DGroup.cs
- WebEventCodes.cs
- BooleanToVisibilityConverter.cs
- DetailsViewRowCollection.cs
- SystemKeyConverter.cs
- FullTrustAssembly.cs
- FormsAuthenticationConfiguration.cs
- WebZone.cs
- PeerInvitationResponse.cs
- ComNativeDescriptor.cs
- SqlNodeAnnotations.cs
- ScrollChrome.cs
- Sql8ConformanceChecker.cs
- XPathMessageFilterElement.cs
- ToolStripLabel.cs
- SqlUdtInfo.cs
- CLSCompliantAttribute.cs
- EventRoute.cs
- ServicePointManager.cs
- dbdatarecord.cs
- StreamBodyWriter.cs
- OracleBinary.cs
- Drawing.cs
- PanelDesigner.cs
- EncryptedType.cs
- SafeBuffer.cs
- ScriptModule.cs
- AnimatedTypeHelpers.cs
- SmtpNetworkElement.cs
- FamilyMap.cs
- OutOfMemoryException.cs
- CommonObjectSecurity.cs
- GridViewAutomationPeer.cs
- WebPartZoneCollection.cs
- ObjectDataSourceView.cs
- ArraySubsetEnumerator.cs
- InvalidateEvent.cs
- Application.cs
- ContextMarshalException.cs
- PreloadedPackages.cs
- InputGestureCollection.cs
- DataBindingCollection.cs
- Stylus.cs
- ECDiffieHellman.cs
- loginstatus.cs
- AttributeSetAction.cs
- AsnEncodedData.cs
- ConsoleKeyInfo.cs
- SafeSecurityHandles.cs
- CatalogPartChrome.cs
- InitiatorSessionSymmetricTransportSecurityProtocol.cs
- CompilationLock.cs
- QueryResults.cs
- ClientScriptManagerWrapper.cs
- URLMembershipCondition.cs
- ErrorInfoXmlDocument.cs
- TileBrush.cs
- EventProviderTraceListener.cs
- LockRecoveryTask.cs
- SchemaImporterExtensionElement.cs
- DbParameterHelper.cs
- ProgramPublisher.cs