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 ()
94 if (Current != null &&
95 Current.NodeType == XPathNodeType.Whitespace &&
96 _nsm is XsltContext &&
97 !((XsltContext) _nsm).PreserveWhitespace (Current))
102 public abstract bool MoveNextCore ();
104 public override string ToString ()
107 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
109 return this.GetType().ToString () + "[" + CurrentPosition + "]";
113 internal class WrapperIterator : BaseIterator
115 XPathNodeIterator iter;
117 public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
123 private WrapperIterator (WrapperIterator other)
126 iter = other.iter.Clone ();
129 public override XPathNodeIterator Clone ()
131 return new WrapperIterator (this);
134 public override bool MoveNextCore ()
136 return iter.MoveNext ();
139 public override XPathNavigator Current {
140 get { return iter.Current; }
143 public override bool RequireSorting {
148 internal abstract class SimpleIterator : BaseIterator
150 protected readonly XPathNavigator _nav;
151 protected XPathNavigator _current;
153 public SimpleIterator (BaseIterator iter) : base (iter.NamespaceManager)
155 _nav = iter.Current.Clone ();
157 protected SimpleIterator (SimpleIterator other, bool clone) : base (other)
159 _nav = other._nav.Clone ();
161 public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
166 public override XPathNavigator Current {
168 if (_current == null) // position == 0
169 _current = _nav.Clone ();
175 internal class SelfIterator : SimpleIterator
177 public SelfIterator (BaseIterator iter) : base (iter) {}
178 public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
179 protected SelfIterator (SelfIterator other, bool clone) : base (other, true)
183 public override XPathNodeIterator Clone () { return new SelfIterator (this, true); }
184 public override bool MoveNextCore ()
186 if (CurrentPosition == 0)
193 public override XPathNavigator Current {
197 public override bool RequireSorting { get { return false; } }
200 internal class NullIterator : SelfIterator
202 public NullIterator (BaseIterator iter) : base (iter) {}
203 public NullIterator (XPathNavigator nav) : this (nav, null) {}
204 public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
205 private NullIterator (NullIterator other) : base (other, true) {}
206 public override XPathNodeIterator Clone () { return new NullIterator (this); }
207 public override bool MoveNextCore ()
213 internal class ParensIterator : BaseIterator
216 public ParensIterator (BaseIterator iter) : base (iter.NamespaceManager)
220 private ParensIterator (ParensIterator other) : base (other)
222 _iter = (BaseIterator) other._iter.Clone ();
224 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
225 public override bool MoveNextCore ()
227 return _iter.MoveNext ();
230 public override XPathNavigator Current { get { return _iter.Current; }}
232 public override bool RequireSorting { get { return _iter.RequireSorting; } }
234 public override int Count { get { return _iter.Count; } }
237 internal class ParentIterator : SimpleIterator
240 public ParentIterator (BaseIterator iter) : base (iter)
242 canMove = _nav.MoveToParent ();
245 private ParentIterator (ParentIterator other, bool dummy) : base (other, true)
248 canMove = other.canMove;
250 public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
251 public override XPathNodeIterator Clone () { return new ParentIterator (this, true); }
252 public override bool MoveNextCore ()
260 public override bool ReverseAxis { get { return true; } }
262 public override bool RequireSorting { get { return false; } }
265 internal class ChildIterator : SimpleIterator
267 public ChildIterator (BaseIterator iter) : base (iter) {}
268 private ChildIterator (ChildIterator other) : base (other, true) {}
269 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
270 public override bool MoveNextCore ()
272 bool fSuccess = (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
274 Current.MoveTo (_nav);
279 public override bool RequireSorting { get { return false; } }
282 internal class FollowingSiblingIterator : SimpleIterator
284 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
285 private FollowingSiblingIterator (FollowingSiblingIterator other) : base (other, true) {}
286 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
287 public override bool MoveNextCore ()
289 switch (_nav.NodeType) {
290 case XPathNodeType.Attribute:
291 case XPathNodeType.Namespace:
292 // They have no siblings.
295 if (_nav.MoveToNext ())
297 Current.MoveTo (_nav);
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 ();
316 private PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other, true)
318 startPosition = other.startPosition;
319 started = other.started;
320 finished = other.finished;
323 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
324 public override bool MoveNextCore ()
330 switch (_nav.NodeType) {
331 case XPathNodeType.Attribute:
332 case XPathNodeType.Namespace:
333 // They have no siblings.
339 if (!_nav.IsSamePosition (startPosition)) {
340 Current.MoveTo (_nav);
344 if (!_nav.MoveToNext ()) {
349 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
350 // Note that if _nav contains only 1 node, it won't be Same.
354 Current.MoveTo (_nav);
358 public override bool ReverseAxis {
362 public override bool RequireSorting { get { return true; } }
365 internal class AncestorIterator : SimpleIterator
368 ArrayList navigators;
369 XPathNavigator startPosition;
371 public AncestorIterator (BaseIterator iter) : base (iter)
373 startPosition = iter.Current.Clone ();
376 private AncestorIterator (AncestorIterator other)
379 startPosition = other.startPosition;
380 if (other.navigators != null)
381 navigators = (ArrayList) other.navigators.Clone ();
382 currentPosition = other.currentPosition;
385 public override XPathNodeIterator Clone ()
387 return new AncestorIterator (this);
390 private void CollectResults ()
392 navigators = new ArrayList ();
394 XPathNavigator ancestors = startPosition.Clone ();
395 if (!ancestors.MoveToParent ())
397 while (ancestors.NodeType != XPathNodeType.Root) {
398 navigators.Add (ancestors.Clone ());
399 ancestors.MoveToParent ();
401 currentPosition = navigators.Count;
404 public override bool MoveNextCore ()
406 if (navigators == null) {
408 if (startPosition.NodeType != XPathNodeType.Root) {
409 // First time it returns Root
411 Current.MoveTo (_nav);
415 if (currentPosition == 0)
417 _nav.MoveTo ((XPathNavigator) navigators [--currentPosition]);
418 Current.MoveTo (_nav);
422 public override bool ReverseAxis {
426 public override bool RequireSorting { get { return true; } }
428 public override int Count {
430 if (navigators == null)
432 return navigators.Count;
437 internal class AncestorOrSelfIterator : SimpleIterator
440 ArrayList navigators;
441 XPathNavigator startPosition;
443 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
445 startPosition = iter.Current.Clone ();
448 private AncestorOrSelfIterator (AncestorOrSelfIterator other)
451 startPosition = other.startPosition;
452 if (other.navigators != null)
453 navigators = (ArrayList) other.navigators.Clone ();
454 currentPosition = other.currentPosition;
457 public override XPathNodeIterator Clone ()
459 return new AncestorOrSelfIterator (this);
462 private void CollectResults ()
464 navigators = new ArrayList ();
466 XPathNavigator ancestors = startPosition.Clone ();
467 if (!ancestors.MoveToParent ())
469 while (ancestors.NodeType != XPathNodeType.Root) {
470 navigators.Add (ancestors.Clone ());
471 ancestors.MoveToParent ();
473 currentPosition = navigators.Count;
476 public override bool MoveNextCore ()
478 if (navigators == null) {
480 if (startPosition.NodeType != XPathNodeType.Root) {
481 // First time it returns Root
483 Current.MoveTo (_nav);
487 if (currentPosition == -1)
489 if (currentPosition-- == 0) {
490 _nav.MoveTo (startPosition);
491 Current.MoveTo (_nav);
492 return true; // returns self.
494 _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
495 Current.MoveTo (_nav);
499 public override bool ReverseAxis {
503 public override bool RequireSorting { get { return true; } }
505 public override int Count {
507 if (navigators == null)
509 return navigators.Count + 1;
514 internal class DescendantIterator : SimpleIterator
517 private bool _finished;
519 public DescendantIterator (BaseIterator iter) : base (iter) {}
521 private DescendantIterator (DescendantIterator other) : base (other)
523 _depth = other._depth;
524 _finished = other._finished;
527 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
529 public override bool MoveNextCore ()
534 if (_nav.MoveToFirstChild ())
537 Current.MoveTo (_nav);
542 if (_nav.MoveToNext ())
544 Current.MoveTo (_nav);
547 if (!_nav.MoveToParent ()) // should NEVER fail!
548 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
555 public override bool RequireSorting { get { return false; } }
558 internal class DescendantOrSelfIterator : SimpleIterator
561 private bool _finished;
563 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
565 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
567 _depth = other._depth;
570 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
572 public override bool MoveNextCore ()
577 if (CurrentPosition == 0)
580 Current.MoveTo (_nav);
583 if (_nav.MoveToFirstChild ())
586 Current.MoveTo (_nav);
591 if (_nav.MoveToNext ())
593 Current.MoveTo (_nav);
596 if (!_nav.MoveToParent ()) // should NEVER fail!
597 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
604 public override bool RequireSorting { get { return false; } }
607 internal class FollowingIterator : SimpleIterator
609 private bool _finished = false;
610 public FollowingIterator (BaseIterator iter) : base (iter) {}
611 private FollowingIterator (FollowingIterator other) : base (other, true) {}
612 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
613 public override bool MoveNextCore ()
617 bool checkChildren = true;
618 if (CurrentPosition == 0)
620 checkChildren = false;
621 switch (_nav.NodeType) {
622 case XPathNodeType.Attribute:
623 case XPathNodeType.Namespace:
624 _nav.MoveToParent ();
625 checkChildren = true;
628 if (_nav.MoveToNext ())
630 Current.MoveTo (_nav);
633 while (_nav.MoveToParent ()) {
634 if (_nav.MoveToNext ()) {
635 Current.MoveTo (_nav);
645 if (_nav.MoveToFirstChild ())
647 Current.MoveTo (_nav);
652 if (_nav.MoveToNext ())
654 Current.MoveTo (_nav);
658 while (_nav.MoveToParent ());
664 public override bool RequireSorting { get { return false; } }
667 internal class PrecedingIterator : SimpleIterator
671 XPathNavigator startPosition;
673 public PrecedingIterator (BaseIterator iter) : base (iter)
675 startPosition = iter.Current.Clone ();
677 private PrecedingIterator (PrecedingIterator other) : base (other, true)
679 startPosition = other.startPosition;
680 started = other.started;
681 finished = other.finished;
683 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
684 public override bool MoveNextCore ()
694 while (!_nav.MoveToFirstChild ()) {
695 while (!_nav.MoveToNext ()) {
696 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
703 if (_nav.IsDescendant (startPosition))
708 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
709 // Note that if _nav contains only 1 node, it won't be Same.
713 Current.MoveTo (_nav);
717 public override bool ReverseAxis {
721 public override bool RequireSorting { get { return true; } }
724 internal class NamespaceIterator : SimpleIterator
726 public NamespaceIterator (BaseIterator iter) : base (iter) {}
727 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
728 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
729 public override bool MoveNextCore ()
731 if (CurrentPosition == 0)
733 if (_nav.MoveToFirstNamespace ())
735 Current.MoveTo (_nav);
739 else if (_nav.MoveToNextNamespace ())
741 Current.MoveTo (_nav);
747 public override bool ReverseAxis { get { return true; } }
748 public override bool RequireSorting { get { return false; } }
751 internal class AttributeIterator : SimpleIterator
753 public AttributeIterator (BaseIterator iter) : base (iter) {}
754 private AttributeIterator (AttributeIterator other) : base (other, true) {}
755 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
756 public override bool MoveNextCore ()
758 if (CurrentPosition == 0)
760 if (_nav.MoveToFirstAttribute ())
762 Current.MoveTo (_nav);
766 else if (_nav.MoveToNextAttribute ())
768 Current.MoveTo (_nav);
774 public override bool RequireSorting { get { return true; } }
777 internal class AxisIterator : BaseIterator
779 private SimpleIterator _iter;
780 private NodeTest _test;
783 XPathNodeType matchType;
785 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter.NamespaceManager)
789 test.GetInfo (out name, out ns, out matchType, NamespaceManager);
791 // name = Current.NameTable.Add (name);
794 // ns = Current.NameTable.Add (ns);
797 private AxisIterator (AxisIterator other) : base (other)
799 _iter = (SimpleIterator) other._iter.Clone ();
803 matchType = other.matchType;
805 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
807 public override bool MoveNextCore ()
809 while (_iter.MoveNext ())
811 if (_test.Match (NamespaceManager, Current))
818 public override XPathNavigator Current { get { return _iter.Current; }}
820 public override bool ReverseAxis {
821 get { return _iter.ReverseAxis; }
824 public override bool RequireSorting { get { return _iter.RequireSorting; } }
827 internal class SimpleSlashIterator : BaseIterator
829 private NodeSet _expr;
830 private BaseIterator _left, _right;
831 private XPathNavigator _current;
833 public SimpleSlashIterator (BaseIterator left, NodeSet expr)
834 : base (left.NamespaceManager)
840 private SimpleSlashIterator (SimpleSlashIterator other)
844 _left = (BaseIterator) other._left.Clone ();
845 if (other._right != null)
846 _right = (BaseIterator) other._right.Clone ();
849 public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
851 public override bool MoveNextCore ()
853 while (_right == null || !_right.MoveNext ()) {
854 if (!_left.MoveNext ())
856 _right = _expr.EvaluateNodeSet (_left);
858 if (_current == null)
859 _current = _right.Current.Clone ();
861 _current.MoveTo (_right.Current);
865 public override XPathNavigator Current {
866 get { return _current; }
869 public override bool RequireSorting {
870 // It always does not need to be sorted.
871 get { return false; }
875 internal class SlashIterator : BaseIterator
877 private BaseIterator _iterLeft;
878 private BaseIterator _iterRight;
879 private NodeSet _expr;
881 SortedList _iterList;
883 BaseIterator _nextIterRight;
885 public SlashIterator (BaseIterator iter, NodeSet expr, bool requireSorting) : base (iter.NamespaceManager)
894 private SlashIterator (SlashIterator other) : base (other)
896 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
897 if (other._iterRight != null)
898 _iterRight = (BaseIterator) other._iterRight.Clone ();
900 if (other._iterList != null)
901 _iterList = (SortedList) other._iterList.Clone ();
902 if (other._navStore != null)
903 _navStore = (ArrayList) other._navStore.Clone ();
904 _finished = other._finished;
905 if (other._nextIterRight != null)
906 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
908 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
910 public override bool MoveNextCore ()
914 if (_navStore != null) {
915 // Which requires sorting::
916 if (_navStore.Count < CurrentPosition + 1) {
920 while (_navStore.Count > CurrentPosition + 1) {
921 if (((XPathNavigator) _navStore [CurrentPosition + 1]).IsSamePosition (
922 (XPathNavigator) _navStore [CurrentPosition]))
923 _navStore.RemoveAt (CurrentPosition + 1);
930 // Which does not require sorting::
932 if (_iterRight == null) { // First time
933 if (!_iterLeft.MoveNext ())
935 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
936 _iterList = new SortedList (XPathIteratorComparer.Instance);
940 while (!_iterRight.MoveNext ()) {
941 if (_iterList.Count > 0) {
942 int last = _iterList.Count - 1;
943 _iterRight = (BaseIterator) _iterList.GetByIndex (last);
944 _iterList.RemoveAt (last);
946 } else if (_nextIterRight != null) {
947 _iterRight = _nextIterRight;
948 _nextIterRight = null;
950 } else if (!_iterLeft.MoveNext ()) {
955 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
960 if (_nextIterRight == null) {
961 bool noMoreNext = false;
962 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
963 if(_iterLeft.MoveNext ())
964 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
971 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
973 if (_nextIterRight != null) {
974 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
975 case XmlNodeOrder.After:
976 _iterList [_iterRight] = _iterRight;
977 _iterRight = _nextIterRight;
978 _nextIterRight = null;
981 case XmlNodeOrder.Same:
982 if (!_nextIterRight.MoveNext ())
983 _nextIterRight = null;
986 int last = _iterList.Count;
987 _iterList [_nextIterRight] = _nextIterRight;
988 if (last != _iterList.Count) {
989 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
990 _iterList.RemoveAt (last);
1003 private void CollectResults ()
1005 _navStore = new ArrayList ();
1007 while (_iterRight == null || !_iterRight.MoveNext ()) {
1008 if (!_iterLeft.MoveNext ()) {
1009 _navStore.Sort (XPathNavigatorComparer.Instance);
1012 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
1014 XPathNavigator nav = _iterRight.Current;
1015 _navStore.Add (nav.Clone ());
1019 public override XPathNavigator Current {
1021 if (CurrentPosition <= 0) return null;
1022 if (_navStore != null) {
1023 return (XPathNavigator) _navStore [CurrentPosition - 1];
1025 return _iterRight.Current;
1030 public override bool RequireSorting {
1031 // It always does not need to be sorted.
1032 get { return false; }
1035 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
1038 internal class PredicateIterator : BaseIterator
1040 private BaseIterator _iter;
1041 private Expression _pred;
1042 private XPathResultType resType;
1043 private bool finished;
1045 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter.NamespaceManager)
1049 resType = pred.GetReturnType (iter);
1052 private PredicateIterator (PredicateIterator other) : base (other)
1054 _iter = (BaseIterator) other._iter.Clone ();
1055 _pred = other._pred;
1056 resType = other.resType;
1057 finished = other.finished;
1059 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1061 public override bool MoveNextCore ()
1065 while (_iter.MoveNext ())
1068 case XPathResultType.Number:
1069 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1073 case XPathResultType.Any: {
1074 object result = _pred.Evaluate (_iter);
1075 if (result is double)
1077 if ((double) result != _iter.ComparablePosition)
1081 else if (!XPathFunctions.ToBoolean (result))
1086 if (!_pred.EvaluateBoolean (_iter))
1095 public override XPathNavigator Current { get { return _iter.Current; }}
1096 public override bool ReverseAxis {
1097 get { return _iter.ReverseAxis; }
1100 public override bool RequireSorting { get { return _iter.RequireSorting; } }
1103 internal class ListIterator : BaseIterator
1105 private IList _list;
1106 bool _requireSorting;
1108 public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter.NamespaceManager)
1110 if (!(list is ICloneable))
1111 throw new ArgumentException ("Target enumerator must be cloneable.");
1113 _requireSorting = requireSorting;
1116 public ListIterator (IList list, NSResolver nsm, bool requireSorting) : base (nsm)
1118 if (!(list is ICloneable))
1119 throw new ArgumentException ("Target enumerator must be cloneable.");
1121 _requireSorting = requireSorting;
1124 private ListIterator (ListIterator other) : base (other)
1126 ICloneable listClone = other._list as ICloneable;
1127 _list = (IList) listClone.Clone ();
1128 _requireSorting = other._requireSorting;
1130 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1132 public override bool MoveNextCore ()
1134 if (CurrentPosition >= _list.Count)
1138 public override XPathNavigator Current {
1140 if (_list.Count == 0)
1142 return (XPathNavigator) _list [CurrentPosition - 1];
1146 public override bool RequireSorting { get { return _requireSorting; } }
1148 public override int Count { get { return _list.Count; } }
1152 internal class UnionIterator : BaseIterator
1154 private BaseIterator _left, _right;
1155 private bool keepLeft;
1156 private bool keepRight;
1157 XPathNavigator _current;
1159 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1165 private UnionIterator (UnionIterator other) : base (other)
1167 _left = (BaseIterator) other._left.Clone ();
1168 _right = (BaseIterator) other._right.Clone ();
1169 keepLeft = other.keepLeft;
1170 keepRight = other.keepRight;
1171 if (other._current != null)
1172 _current = other._current.Clone ();
1174 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1176 public override bool MoveNextCore ()
1179 keepLeft = _left.MoveNext ();
1181 keepRight = _right.MoveNext ();
1183 if (!keepLeft && !keepRight)
1190 } else if (!keepLeft) {
1192 SetCurrent (_right);
1196 switch (_left.Current.ComparePosition (_right.Current)) {
1197 case XmlNodeOrder.Same:
1198 // consume both. i.e. don't output duplicate result.
1199 keepLeft = keepRight = false;
1200 SetCurrent (_right);
1202 case XmlNodeOrder.Before:
1203 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1207 case XmlNodeOrder.After:
1209 SetCurrent (_right);
1212 throw new InvalidOperationException ("Should not happen.");
1216 private void SetCurrent (XPathNodeIterator iter)
1218 if (_current == null)
1219 _current = iter.Current.Clone ();
1221 _current.MoveTo (iter.Current);
1224 public override XPathNavigator Current
1226 get { return _current; }
1229 public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }