The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.Runtime \ FollowingSiblingIterator

  1. //------------------------------------------------------------------------------
  2. // <copyright file="SiblingIterators.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Xml;
  17. using System.Xml.XPath;
  18. using System.Xml.Schema;
  19. using System.Diagnostics;
  20. using System.Collections;
  21. using System.ComponentModel;
  22. namespace System.Xml.Xsl.Runtime
  23. {
  24.    
  25.     /// <summary>
  26.     /// Iterate over all following-sibling content nodes.
  27.     /// </summary>
  28.     [EditorBrowsable(EditorBrowsableState.Never)]
  29.     public struct FollowingSiblingIterator
  30.     {
  31.         private XmlNavigatorFilter filter;
  32.         private XPathNavigator navCurrent;
  33.        
  34.         /// <summary>
  35.         /// Initialize the FollowingSiblingIterator.
  36.         /// </summary>
  37.         public void Create(XPathNavigator context, XmlNavigatorFilter filter)
  38.         {
  39.             this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, context);
  40.             this.filter = filter;
  41.         }
  42.        
  43.         /// <summary>
  44.         /// Position the iterator on the next following-sibling node. Return true if such a node exists and
  45.         /// set Current property. Otherwise, return false (Current property is undefined).
  46.         /// </summary>
  47.         public bool MoveNext()
  48.         {
  49.             return this.filter.MoveToFollowingSibling(this.navCurrent);
  50.         }
  51.        
  52.         /// <summary>
  53.         /// Return the current result navigator. This is only defined after MoveNext() has returned true.
  54.         /// </summary>
  55.         public XPathNavigator Current {
  56.             get { return this.navCurrent; }
  57.         }
  58.     }
  59.    
  60.    
  61.     /// <summary>
  62.     /// Iterate over child following-sibling nodes. This is a simple variation on the ContentMergeIterator, so use containment
  63.     /// to reuse its code (can't use inheritance with structures).
  64.     /// </summary>
  65.     [EditorBrowsable(EditorBrowsableState.Never)]
  66.     public struct FollowingSiblingMergeIterator
  67.     {
  68.         private ContentMergeIterator wrapped;
  69.        
  70.         /// <summary>
  71.         /// Initialize the FollowingSiblingMergeIterator.
  72.         /// </summary>
  73.         public void Create(XmlNavigatorFilter filter)
  74.         {
  75.             this.wrapped.Create(filter);
  76.         }
  77.        
  78.         /// <summary>
  79.         /// Position this iterator to the next content or sibling node. Return IteratorResult.NoMoreNodes if there are
  80.         /// no more content or sibling nodes. Return IteratorResult.NeedInputNode if the next input node needs to be
  81.         /// fetched first. Return IteratorResult.HaveCurrent if the Current property is set to the next node in the
  82.         /// iteration.
  83.         /// </summary>
  84.         public IteratorResult MoveNext(XPathNavigator navigator)
  85.         {
  86.             return this.wrapped.MoveNext(navigator, false);
  87.         }
  88.        
  89.         /// <summary>
  90.         /// Return the current result navigator. This is only defined after MoveNext() has returned IteratorResult.HaveCurrent.
  91.         /// </summary>
  92.         public XPathNavigator Current {
  93.             get { return this.wrapped.Current; }
  94.         }
  95.     }
  96.    
  97.    
  98.     /// <summary>
  99.     /// Iterate over all preceding nodes according to XPath preceding axis rules, returning nodes in reverse
  100.     /// document order.
  101.     /// </summary>
  102.     [EditorBrowsable(EditorBrowsableState.Never)]
  103.     public struct PrecedingSiblingIterator
  104.     {
  105.         private XmlNavigatorFilter filter;
  106.         private XPathNavigator navCurrent;
  107.        
  108.         /// <summary>
  109.         /// Initialize the PrecedingSiblingIterator.
  110.         /// </summary>
  111.         public void Create(XPathNavigator context, XmlNavigatorFilter filter)
  112.         {
  113.             this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, context);
  114.             this.filter = filter;
  115.         }
  116.        
  117.         /// <summary>
  118.         /// Return true if the Current property is set to the next Preceding node in reverse document order.
  119.         /// </summary>
  120.         public bool MoveNext()
  121.         {
  122.             return this.filter.MoveToPreviousSibling(this.navCurrent);
  123.         }
  124.        
  125.         /// <summary>
  126.         /// Return the current result navigator. This is only defined after MoveNext() has returned true.
  127.         /// </summary>
  128.         public XPathNavigator Current {
  129.             get { return this.navCurrent; }
  130.         }
  131.     }
  132.    
  133.    
  134.     /// <summary>
  135.     /// Iterate over all preceding-sibling content nodes in document order.
  136.     /// </summary>
  137.     [EditorBrowsable(EditorBrowsableState.Never)]
  138.     public struct PrecedingSiblingDocOrderIterator
  139.     {
  140.         private XmlNavigatorFilter filter;
  141.         private XPathNavigator navCurrent, navEnd;
  142.         private bool needFirst, useCompPos;
  143.        
  144.         /// <summary>
  145.         /// Initialize the PrecedingSiblingDocOrderIterator.
  146.         /// </summary>
  147.         public void Create(XPathNavigator context, XmlNavigatorFilter filter)
  148.         {
  149.             this.filter = filter;
  150.             this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, context);
  151.             this.navEnd = XmlQueryRuntime.SyncToNavigator(this.navEnd, context);
  152.             this.needFirst = true;
  153.            
  154.             // If the context node will be filtered out, then use ComparePosition to
  155.             // determine when the context node has been passed by. Otherwise, IsSamePosition
  156.             // is sufficient to determine when the context node has been reached.
  157.             this.useCompPos = this.filter.IsFiltered(context);
  158.         }
  159.        
  160.         /// <summary>
  161.         /// Position the iterator on the next preceding-sibling node. Return true if such a node exists and
  162.         /// set Current property. Otherwise, return false (Current property is undefined).
  163.         /// </summary>
  164.         public bool MoveNext()
  165.         {
  166.             if (this.needFirst) {
  167.                 // Get first matching preceding-sibling node
  168.                 if (!this.navCurrent.MoveToParent())
  169.                     return false;
  170.                
  171.                 if (!this.filter.MoveToContent(this.navCurrent))
  172.                     return false;
  173.                
  174.                 this.needFirst = false;
  175.             }
  176.             else {
  177.                 // Get next matching preceding-sibling node
  178.                 if (!this.filter.MoveToFollowingSibling(this.navCurrent))
  179.                     return false;
  180.             }
  181.            
  182.             // Accept matching sibling only if it precedes navEnd in document order
  183.             if (this.useCompPos)
  184.                 return (this.navCurrent.ComparePosition(this.navEnd) == XmlNodeOrder.Before);
  185.            
  186.             if (this.navCurrent.IsSamePosition(this.navEnd)) {
  187.                 // Found the original context node, so iteration is complete. If MoveNext
  188.                 // is called again, use ComparePosition so that false will continue to be
  189.                 // returned.
  190.                 this.useCompPos = true;
  191.                 return false;
  192.             }
  193.            
  194.             return true;
  195.         }
  196.        
  197.         /// <summary>
  198.         /// Return the current result navigator. This is only defined after MoveNext() has returned true.
  199.         /// </summary>
  200.         public XPathNavigator Current {
  201.             get { return this.navCurrent; }
  202.         }
  203.     }
  204. }

Developer Fusion