2 // System.Xml.XPath.BaseIterator
5 // Piers Haken (piersh@friskit.com)
6 // Atsushi Enomoto (atsushi@ximian.com)
8 // (C) 2002 Piers Haken
9 // (C) 2003 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
36 using System.Xml.XPath;
40 using NSResolver = System.Xml.IXmlNamespaceResolver;
42 using NSResolver = System.Xml.XmlNamespaceManager;
45 namespace System.Xml.XPath
47 internal abstract class BaseIterator : XPathNodeIterator
52 internal BaseIterator (BaseIterator other)
55 position = other.position;
57 internal BaseIterator (NSResolver nsm)
62 public NSResolver NamespaceManager
68 public virtual bool ReverseAxis {
72 public abstract bool RequireSorting { get; }
74 public virtual int ComparablePosition {
77 int diff = Count - CurrentPosition + 1;
78 return diff < 1 ? 1 : diff;
81 return CurrentPosition;
85 public override int CurrentPosition {
86 get { return position; }
89 public override bool MoveNext ()
97 public abstract bool MoveNextCore ();
99 public override string ToString ()
102 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
104 return this.GetType().ToString () + "[" + CurrentPosition + "]";
108 internal class WrapperIterator : BaseIterator
110 XPathNodeIterator iter;
112 public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
118 private WrapperIterator (WrapperIterator other)
121 iter = other.iter.Clone ();
124 public override XPathNodeIterator Clone ()
126 return new WrapperIterator (this);
129 public override bool MoveNextCore ()
131 return iter.MoveNext ();
134 public override XPathNavigator Current {
135 get { return iter.Current; }
138 public override bool RequireSorting {
143 internal abstract class SimpleIterator : BaseIterator
145 protected readonly BaseIterator _iter;
146 protected readonly XPathNavigator _nav;
147 protected XPathNavigator _current;
149 public SimpleIterator (BaseIterator iter) : base (iter.NamespaceManager)
152 _nav = iter.Current.Clone ();
154 protected SimpleIterator (SimpleIterator other, bool clone) : base (other)
156 if (other._nav == null)
157 _iter = (BaseIterator) other._iter.Clone ();
159 _nav = other._nav.Clone ();
160 // if (other._current != null)
161 // _current = other._current.Clone ();
163 public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
168 public override XPathNavigator Current {
170 if (_current == null) // position == 0
171 _current = _nav.Clone ();
177 internal class SelfIterator : SimpleIterator
179 public SelfIterator (BaseIterator iter) : base (iter) {}
180 public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
181 protected SelfIterator (SelfIterator other, bool clone) : base (other, true)
183 if (other._current != null)
187 public override XPathNodeIterator Clone () { return new SelfIterator (this, true); }
188 public override bool MoveNextCore ()
190 if (CurrentPosition == 0)
198 public override bool RequireSorting { get { return false; } }
201 internal class NullIterator : SelfIterator
203 public NullIterator (BaseIterator iter) : base (iter) {}
204 public NullIterator (XPathNavigator nav) : this (nav, null) {}
205 public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
206 private NullIterator (NullIterator other) : base (other, true) {}
207 public override XPathNodeIterator Clone () { return new NullIterator (this); }
208 public override bool MoveNextCore ()
214 internal class ParensIterator : BaseIterator
217 public ParensIterator (BaseIterator iter) : base (iter.NamespaceManager)
221 private ParensIterator (ParensIterator other) : base (other)
223 _iter = (BaseIterator) other._iter.Clone ();
225 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
226 public override bool MoveNextCore ()
228 return _iter.MoveNext ();
231 public override XPathNavigator Current { get { return _iter.Current; }}
233 public override bool RequireSorting { get { return _iter.RequireSorting; } }
235 public override int Count { get { return _iter.Count; } }
238 internal class ParentIterator : SimpleIterator
240 public ParentIterator (BaseIterator iter) : base (iter) {}
241 private ParentIterator (ParentIterator other) : base (other, true)
243 if (other._current != null)
246 public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
247 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
248 public override bool MoveNextCore ()
250 if (CurrentPosition == 0 && _nav.MoveToParent ())
258 public override bool ReverseAxis { get { return true; } }
260 public override bool RequireSorting { get { return false; } }
263 internal class ChildIterator : SimpleIterator
265 public ChildIterator (BaseIterator iter) : base (iter) {}
266 private ChildIterator (ChildIterator other) : base (other, true) {}
267 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
268 public override bool MoveNextCore ()
270 bool fSuccess = (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
272 // This clone cannot be omitted
273 _current = _nav.Clone ();
278 public override bool RequireSorting { get { return false; } }
281 internal class FollowingSiblingIterator : SimpleIterator
283 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
284 private FollowingSiblingIterator (FollowingSiblingIterator other) : base (other, true) {}
285 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
286 public override bool MoveNextCore ()
288 switch (_nav.NodeType) {
289 case XPathNodeType.Attribute:
290 case XPathNodeType.Namespace:
291 // They have no siblings.
294 if (_nav.MoveToNext ())
296 // This clone cannot be omitted
297 _current = _nav.Clone ();
303 public override bool RequireSorting { get { return false; } }
306 internal class PrecedingSiblingIterator : SimpleIterator
310 XPathNavigator startPosition;
312 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
314 startPosition = iter.Current.Clone ();
315 _current = startPosition.Clone ();
317 private PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other, true)
319 startPosition = other.startPosition;
320 started = other.started;
321 finished = other.finished;
322 if (other._current != null)
323 _current = other._current.Clone ();
326 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
327 public override bool MoveNextCore ()
333 switch (_nav.NodeType) {
334 case XPathNodeType.Attribute:
335 case XPathNodeType.Namespace:
336 // They have no siblings.
342 if (!_nav.IsSamePosition (startPosition)) {
343 // This clone cannot be omitted
344 _current = _nav.Clone ();
348 if (!_nav.MoveToNext ()) {
353 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
354 // Note that if _nav contains only 1 node, it won't be Same.
358 // This clone cannot be omitted
359 _current = _nav.Clone ();
363 public override bool ReverseAxis {
367 public override bool RequireSorting { get { return true; } }
370 internal class AncestorIterator : SimpleIterator
373 ArrayList navigators;
374 XPathNavigator startPosition;
376 public AncestorIterator (BaseIterator iter) : base (iter)
378 startPosition = iter.Current.Clone ();
379 _current = startPosition.Clone ();
382 private AncestorIterator (AncestorIterator other)
385 startPosition = other.startPosition;
386 if (other.navigators != null)
387 navigators = (ArrayList) other.navigators.Clone ();
388 if (other._current != null)
389 _current = other._current.Clone ();
390 currentPosition = other.currentPosition;
393 public override XPathNodeIterator Clone ()
395 return new AncestorIterator (this);
398 private void CollectResults ()
400 navigators = new ArrayList ();
402 XPathNavigator ancestors = startPosition.Clone ();
403 if (!ancestors.MoveToParent ())
405 while (ancestors.NodeType != XPathNodeType.Root) {
406 navigators.Add (ancestors.Clone ());
407 ancestors.MoveToParent ();
409 currentPosition = navigators.Count;
412 public override bool MoveNextCore ()
414 if (navigators == null) {
416 if (startPosition.NodeType != XPathNodeType.Root) {
417 // First time it returns Root
418 // This clone cannot be omitted
420 _current = _nav.Clone ();
424 if (currentPosition == 0)
426 _nav.MoveTo ((XPathNavigator) navigators [--currentPosition]);
427 _current = _nav.Clone ();
431 public override bool ReverseAxis {
435 public override bool RequireSorting { get { return true; } }
437 public override int Count {
439 if (navigators == null)
441 return navigators.Count;
446 internal class AncestorOrSelfIterator : SimpleIterator
449 ArrayList navigators;
450 XPathNavigator startPosition;
452 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
454 startPosition = iter.Current.Clone ();
455 _current = startPosition.Clone ();
458 private AncestorOrSelfIterator (AncestorOrSelfIterator other)
461 startPosition = other.startPosition;
462 if (other.navigators != null)
463 navigators = (ArrayList) other.navigators.Clone ();
464 if (other._current != null)
465 _current = other._current.Clone ();
466 currentPosition = other.currentPosition;
469 public override XPathNodeIterator Clone ()
471 return new AncestorOrSelfIterator (this);
474 private void CollectResults ()
476 navigators = new ArrayList ();
478 XPathNavigator ancestors = startPosition.Clone ();
479 if (!ancestors.MoveToParent ())
481 while (ancestors.NodeType != XPathNodeType.Root) {
482 navigators.Add (ancestors.Clone ());
483 ancestors.MoveToParent ();
485 currentPosition = navigators.Count;
488 public override bool MoveNextCore ()
490 if (navigators == null) {
492 if (startPosition.NodeType != XPathNodeType.Root) {
493 // First time it returns Root
494 // This clone cannot be omitted
496 _current = _nav.Clone ();
500 if (currentPosition == -1)
502 if (currentPosition-- == 0) {
503 _nav.MoveTo (startPosition);
504 _current = _nav.Clone ();
505 return true; // returns self.
507 _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
508 _current = _nav.Clone ();
512 public override bool ReverseAxis {
516 public override bool RequireSorting { get { return true; } }
518 public override int Count {
520 if (navigators == null)
522 return navigators.Count + 1;
527 internal class DescendantIterator : SimpleIterator
530 private bool _finished;
532 public DescendantIterator (BaseIterator iter) : base (iter) {}
534 private DescendantIterator (DescendantIterator other) : base (other)
536 _depth = other._depth;
537 _finished = other._finished;
538 if (other._current != null)
539 _current = other._current.Clone ();
542 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
544 public override bool MoveNextCore ()
549 if (_nav.MoveToFirstChild ())
552 // This clone cannot be omitted
553 _current = _nav.Clone ();
558 if (_nav.MoveToNext ())
560 // This clone cannot be omitted
561 _current = _nav.Clone ();
564 if (!_nav.MoveToParent ()) // should NEVER fail!
565 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
572 public override bool RequireSorting { get { return false; } }
575 internal class DescendantOrSelfIterator : SimpleIterator
578 private bool _finished;
580 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
582 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
584 _depth = other._depth;
585 if (other._current != null)
586 _current = other._current.Clone ();
589 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
591 public override bool MoveNextCore ()
596 if (CurrentPosition == 0)
599 // This clone cannot be omitted
600 _current = _nav.Clone ();
603 if (_nav.MoveToFirstChild ())
606 // This clone cannot be omitted
607 _current = _nav.Clone ();
612 if (_nav.MoveToNext ())
614 // This clone cannot be omitted
615 _current = _nav.Clone ();
618 if (!_nav.MoveToParent ()) // should NEVER fail!
619 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
626 public override bool RequireSorting { get { return false; } }
629 internal class FollowingIterator : SimpleIterator
631 private bool _finished = false;
632 public FollowingIterator (BaseIterator iter) : base (iter) {}
633 private FollowingIterator (FollowingIterator other) : base (other, true) {}
634 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
635 public override bool MoveNextCore ()
639 if (CurrentPosition == 0)
641 if (_nav.MoveToNext ())
643 // This clone cannot be omitted
644 _current = _nav.Clone ();
647 while (_nav.MoveToParent ()) {
648 if (_nav.MoveToNext ()) {
649 // This clone cannot be omitted
650 _current = _nav.Clone ();
658 if (_nav.MoveToFirstChild ())
660 // This clone cannot be omitted
661 _current = _nav.Clone ();
666 if (_nav.MoveToNext ())
668 // This clone cannot be omitted
669 _current = _nav.Clone ();
673 while (_nav.MoveToParent ());
679 public override bool RequireSorting { get { return false; } }
682 internal class PrecedingIterator : SimpleIterator
686 XPathNavigator startPosition;
688 public PrecedingIterator (BaseIterator iter) : base (iter)
690 startPosition = iter.Current.Clone ();
691 _current = startPosition.Clone ();
693 private PrecedingIterator (PrecedingIterator other) : base (other, true)
695 startPosition = other.startPosition;
696 started = other.started;
697 finished = other.finished;
698 if (other._current != null)
699 _current = other._current.Clone ();
701 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
702 public override bool MoveNextCore ()
712 while (!_nav.MoveToFirstChild ()) {
713 while (!_nav.MoveToNext ()) {
714 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
721 if (_nav.IsDescendant (startPosition))
726 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
727 // Note that if _nav contains only 1 node, it won't be Same.
731 // This cannot be omitted
732 _current = _nav.Clone ();
736 public override bool ReverseAxis {
740 public override bool RequireSorting { get { return true; } }
743 internal class NamespaceIterator : SimpleIterator
745 public NamespaceIterator (BaseIterator iter) : base (iter) {}
746 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
747 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
748 public override bool MoveNextCore ()
750 if (CurrentPosition == 0)
752 if (_nav.MoveToFirstNamespace ())
754 // This clone cannot be omitted
755 _current = _nav.Clone ();
759 else if (_nav.MoveToNextNamespace ())
761 // This clone cannot be omitted
762 _current = _nav.Clone ();
768 public override bool ReverseAxis { get { return true; } }
769 public override bool RequireSorting { get { return false; } }
772 internal class AttributeIterator : SimpleIterator
774 public AttributeIterator (BaseIterator iter) : base (iter) {}
775 private AttributeIterator (AttributeIterator other) : base (other, true) {}
776 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
777 public override bool MoveNextCore ()
779 if (CurrentPosition == 0)
781 if (_nav.MoveToFirstAttribute ())
783 // This clone cannot be omitted
784 _current = _nav.Clone ();
788 else if (_nav.MoveToNextAttribute ())
790 // This clone cannot be omitted
791 _current = _nav.Clone ();
797 public override bool RequireSorting { get { return false; } }
800 internal class AxisIterator : BaseIterator
802 private SimpleIterator _iter;
803 private NodeTest _test;
806 XPathNodeType matchType;
808 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter.NamespaceManager)
812 test.GetInfo (out name, out ns, out matchType, NamespaceManager);
814 // name = Current.NameTable.Add (name);
817 // ns = Current.NameTable.Add (ns);
820 private AxisIterator (AxisIterator other) : base (other)
822 _iter = (SimpleIterator) other._iter.Clone ();
826 matchType = other.matchType;
828 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
830 public override bool MoveNextCore ()
832 while (_iter.MoveNext ())
834 if (_test.Match (NamespaceManager, Current))
841 public override XPathNavigator Current { get { return _iter.Current; }}
845 if (Current.NodeType != matchType && matchType != XPathNodeType.All)
849 return name == null || (object)name == (object)Current.LocalName;
851 return (object)ns == (object)Current.NamespaceURI &&
852 (name == null || (object)name == (object)Current.LocalName);
854 public override bool ReverseAxis {
855 get { return _iter.ReverseAxis; }
858 public override bool RequireSorting { get { return _iter.RequireSorting; } }
861 internal class SlashIterator : BaseIterator
863 private BaseIterator _iterLeft;
864 private BaseIterator _iterRight;
865 private NodeSet _expr;
867 SortedList _iterList;
869 BaseIterator _nextIterRight;
871 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter.NamespaceManager)
875 if (_iterLeft.RequireSorting || _expr.RequireSorting)
879 private SlashIterator (SlashIterator other) : base (other)
881 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
882 if (other._iterRight != null)
883 _iterRight = (BaseIterator) other._iterRight.Clone ();
885 if (other._iterList != null)
886 _iterList = (SortedList) other._iterList.Clone ();
887 if (other._navStore != null)
888 _navStore = (ArrayList) other._navStore.Clone ();
889 _finished = other._finished;
890 if (other._nextIterRight != null)
891 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
893 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
895 public override bool MoveNextCore ()
899 if (_navStore != null) {
900 // Which requires sorting::
901 if (_navStore.Count < CurrentPosition + 1) {
905 while (_navStore.Count > CurrentPosition + 1) {
906 if (((XPathNavigator) _navStore [CurrentPosition + 1]).IsSamePosition (
907 (XPathNavigator) _navStore [CurrentPosition]))
908 _navStore.RemoveAt (CurrentPosition + 1);
915 // Which does not require sorting::
917 if (_iterRight == null) { // First time
918 if (!_iterLeft.MoveNext ())
920 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
921 _iterList = new SortedList (XPathIteratorComparer.Instance);
925 while (!_iterRight.MoveNext ()) {
926 if (_iterList.Count > 0) {
927 int last = _iterList.Count - 1;
928 BaseIterator tmpIter = (BaseIterator) _iterList.GetByIndex (last);
929 _iterList.RemoveAt (last);
930 switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
931 case XmlNodeOrder.Same:
932 case XmlNodeOrder.Before:
933 _iterRight = tmpIter;
936 _iterRight = tmpIter;
940 } else if (_nextIterRight != null) {
941 _iterRight = _nextIterRight;
942 _nextIterRight = null;
944 } else if (!_iterLeft.MoveNext ()) {
949 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
954 if (_nextIterRight == null) {
955 bool noMoreNext = false;
956 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
957 if(_iterLeft.MoveNext ())
958 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
965 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
967 if (_nextIterRight != null) {
968 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
969 case XmlNodeOrder.After:
970 _iterList.Add (_iterList.Count, _iterRight);
971 _iterRight = _nextIterRight;
972 _nextIterRight = null;
975 case XmlNodeOrder.Same:
976 if (!_nextIterRight.MoveNext ())
977 _nextIterRight = null;
980 int last = _iterList.Count;
982 _iterList.Add (last, _nextIterRight);
983 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
984 _iterList.RemoveAt (last);
997 private void CollectResults ()
999 _navStore = new ArrayList ();
1001 while (_iterRight == null || !_iterRight.MoveNext ()) {
1002 if (!_iterLeft.MoveNext ()) {
1003 _navStore.Sort (XPathNavigatorComparer.Instance);
1006 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
1008 XPathNavigator nav = _iterRight.Current;
1009 _navStore.Add (nav);
1013 public override XPathNavigator Current {
1015 if (CurrentPosition <= 0) return null;
1016 if (_navStore != null) {
1017 return (XPathNavigator) _navStore [CurrentPosition - 1];
1019 return _iterRight.Current;
1024 public override bool RequireSorting {
1025 // It always does not need to be sorted.
1026 get { return false; }
1029 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
1032 internal class PredicateIterator : BaseIterator
1034 private BaseIterator _iter;
1035 private Expression _pred;
1036 private XPathResultType resType;
1038 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter.NamespaceManager)
1042 resType = pred.GetReturnType (iter);
1045 private PredicateIterator (PredicateIterator other) : base (other)
1047 _iter = (BaseIterator) other._iter.Clone ();
1048 _pred = other._pred;
1049 resType = other.resType;
1051 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1053 public override bool MoveNextCore ()
1055 while (_iter.MoveNext ())
1058 case XPathResultType.Number:
1059 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1062 case XPathResultType.Any: {
1063 object result = _pred.Evaluate (_iter);
1064 if (result is double)
1066 if ((double) result != _iter.ComparablePosition)
1069 else if (!XPathFunctions.ToBoolean (result))
1074 if (!_pred.EvaluateBoolean (_iter))
1083 public override XPathNavigator Current { get { return _iter.Current; }}
1084 public override bool ReverseAxis {
1085 get { return _iter.ReverseAxis; }
1088 public override bool RequireSorting { get { return _iter.RequireSorting || _pred.RequireSorting; } }
1091 internal class ListIterator : BaseIterator
1093 private IList _list;
1094 bool _requireSorting;
1096 public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter.NamespaceManager)
1098 if (!(list is ICloneable))
1099 throw new ArgumentException ("Target enumerator must be cloneable.");
1101 _requireSorting = requireSorting;
1104 public ListIterator (IList list, NSResolver nsm, bool requireSorting) : base (nsm)
1106 if (!(list is ICloneable))
1107 throw new ArgumentException ("Target enumerator must be cloneable.");
1109 _requireSorting = requireSorting;
1112 private ListIterator (ListIterator other) : base (other)
1114 ICloneable listClone = other._list as ICloneable;
1115 _list = (IList) listClone.Clone ();
1116 _requireSorting = other._requireSorting;
1118 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1120 public override bool MoveNextCore ()
1122 if (CurrentPosition >= _list.Count)
1126 public override XPathNavigator Current {
1128 if (_list.Count == 0)
1130 return (XPathNavigator) _list [CurrentPosition - 1];
1134 public override bool RequireSorting { get { return _requireSorting; } }
1136 public override int Count { get { return _list.Count; } }
1140 internal class UnionIterator : BaseIterator
1142 private BaseIterator _left, _right;
1143 private bool keepLeft;
1144 private bool keepRight;
1145 private bool useRight;
1147 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1153 private UnionIterator (UnionIterator other) : base (other)
1155 _left = (BaseIterator) other._left.Clone ();
1156 _right = (BaseIterator) other._right.Clone ();
1157 keepLeft = other.keepLeft;
1158 keepRight = other.keepRight;
1159 useRight = other.useRight;
1161 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1163 public override bool MoveNextCore ()
1166 keepLeft = _left.MoveNext ();
1168 keepRight = _right.MoveNext ();
1170 if (!keepLeft && !keepRight)
1174 keepLeft = useRight = false;
1176 } else if (!keepLeft) {
1182 switch (_left.Current.ComparePosition (_right.Current)) {
1183 case XmlNodeOrder.Same:
1184 // consume both. i.e. don't output duplicate result.
1185 keepLeft = keepRight = false;
1188 case XmlNodeOrder.Before:
1189 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1190 keepLeft = useRight = false;
1192 case XmlNodeOrder.After:
1197 throw new InvalidOperationException ("Should not happen.");
1200 public override XPathNavigator Current
1204 if (CurrentPosition == 0)
1207 return _right.Current;
1209 return _left.Current;
1213 public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }