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 int ComparablePosition {
75 int diff = Count - CurrentPosition + 1;
76 return diff < 1 ? 1 : diff;
79 return CurrentPosition;
83 public override int CurrentPosition {
84 get { return position; }
87 internal void SetPosition (int pos)
92 public override bool MoveNext ()
94 // FIXME: enable this line once I found the culprit of a breakage in WrapperIterator. And remove it again in the final stage.
95 //if (CurrentPosition == 0 && Current != null) throw new Exception (GetType ().FullName);
102 public abstract bool MoveNextCore ();
104 internal XPathNavigator PeekNext ()
106 XPathNodeIterator i = Clone ();
107 return i.MoveNext () ? i.Current : null;
110 public override string ToString ()
113 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
115 return this.GetType().ToString () + "[" + CurrentPosition + "]";
119 internal class WrapperIterator : BaseIterator
121 XPathNodeIterator iter;
123 public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
129 private WrapperIterator (WrapperIterator other)
132 iter = other.iter.Clone ();
135 public override XPathNodeIterator Clone ()
137 return new WrapperIterator (this);
140 public override bool MoveNextCore ()
142 return iter.MoveNext ();
145 public override XPathNavigator Current {
146 get { return iter.Current; }
150 internal abstract class SimpleIterator : BaseIterator
152 protected readonly XPathNavigator _nav;
153 protected XPathNavigator _current;
156 public SimpleIterator (BaseIterator iter) : base (iter.NamespaceManager)
158 if (iter.CurrentPosition == 0) {
162 if (iter.CurrentPosition > 0)
163 _nav = iter.Current.Clone ();
165 protected SimpleIterator (SimpleIterator other, bool clone) : base (other)
167 if (other._nav != null)
168 _nav = clone ? other._nav.Clone () : other._nav;
169 skipfirst = other.skipfirst;
171 public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
176 public override bool MoveNext ()
180 return false; // empty
182 base.SetPosition (1);
185 return base.MoveNext ();
189 public override XPathNavigator Current {
191 if (CurrentPosition == 0)
199 internal class SelfIterator : SimpleIterator
201 public SelfIterator (BaseIterator iter) : base (iter) {}
202 public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
203 protected SelfIterator (SelfIterator other, bool clone) : base (other, true)
207 public override XPathNodeIterator Clone () { return new SelfIterator (this, true); }
208 public override bool MoveNextCore ()
210 if (CurrentPosition == 0)
217 public override XPathNavigator Current {
218 get { return CurrentPosition == 0 ? null : _nav; }
222 internal class NullIterator : SelfIterator
224 public NullIterator (BaseIterator iter) : base (iter) {}
225 public NullIterator (XPathNavigator nav) : this (nav, null) {}
226 public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
227 private NullIterator (NullIterator other) : base (other, true) {}
228 public override XPathNodeIterator Clone () { return new NullIterator (this); }
229 public override bool MoveNextCore ()
234 public override int CurrentPosition {
238 public override XPathNavigator Current {
243 internal class ParensIterator : BaseIterator
247 public ParensIterator (BaseIterator iter) : base (iter.NamespaceManager)
251 private ParensIterator (ParensIterator other) : base (other)
253 _iter = (BaseIterator) other._iter.Clone ();
255 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
256 public override bool MoveNextCore ()
258 return _iter.MoveNext ();
261 public override XPathNavigator Current { get { return _iter.Current; }}
263 public override int Count { get { return _iter.Count; } }
266 internal class ParentIterator : SimpleIterator
269 public ParentIterator (BaseIterator iter) : base (iter)
271 canMove = _nav.MoveToParent ();
274 private ParentIterator (ParentIterator other, bool dummy) : base (other, true)
277 canMove = other.canMove;
279 public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
280 public override XPathNodeIterator Clone () { return new ParentIterator (this, true); }
281 public override bool MoveNextCore ()
290 internal class ChildIterator : BaseIterator
294 public ChildIterator (BaseIterator iter) : base (iter.NamespaceManager)
296 _nav = iter.CurrentPosition == 0 ? iter.PeekNext () : iter.Current;
297 if (_nav != null && _nav.HasChildren)
298 _nav = _nav.Clone ();
302 private ChildIterator (ChildIterator other) : base (other)
304 _nav = other._nav == null ? null : other._nav.Clone ();
307 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
309 public override bool MoveNextCore ()
314 return (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
317 public override XPathNavigator Current {
319 if (CurrentPosition == 0)
326 internal class FollowingSiblingIterator : SimpleIterator
328 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
329 private FollowingSiblingIterator (FollowingSiblingIterator other) : base (other, true) {}
330 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
331 public override bool MoveNextCore ()
333 switch (_nav.NodeType) {
334 case XPathNodeType.Attribute:
335 case XPathNodeType.Namespace:
336 // They have no siblings.
339 if (_nav.MoveToNext ())
341 // Current.MoveTo (_nav);
348 internal class PrecedingSiblingIterator : SimpleIterator
352 XPathNavigator startPosition;
354 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
356 startPosition = iter.Current.Clone ();
358 private PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other, true)
360 startPosition = other.startPosition;
361 started = other.started;
362 finished = other.finished;
365 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
366 public override bool MoveNextCore ()
372 switch (_nav.NodeType) {
373 case XPathNodeType.Attribute:
374 case XPathNodeType.Namespace:
375 // They have no siblings.
381 if (!_nav.IsSamePosition (startPosition)) {
382 // Current.MoveTo (_nav);
386 if (!_nav.MoveToNext ()) {
391 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
392 // Note that if _nav contains only 1 node, it won't be Same.
396 // Current.MoveTo (_nav);
400 public override bool ReverseAxis {
405 internal class AncestorIterator : SimpleIterator
408 ArrayList navigators;
409 XPathNavigator startPosition;
411 public AncestorIterator (BaseIterator iter) : base (iter)
413 startPosition = iter.Current.Clone ();
416 private AncestorIterator (AncestorIterator other)
419 startPosition = other.startPosition;
420 if (other.navigators != null)
421 navigators = (ArrayList) other.navigators;
422 currentPosition = other.currentPosition;
425 public override XPathNodeIterator Clone ()
427 return new AncestorIterator (this);
430 private void CollectResults ()
432 navigators = new ArrayList ();
434 XPathNavigator ancestors = startPosition.Clone ();
435 while (ancestors.NodeType != XPathNodeType.Root && ancestors.MoveToParent ())
436 navigators.Add (ancestors.Clone ());
437 currentPosition = navigators.Count;
440 public override bool MoveNextCore ()
442 if (navigators == null)
444 if (currentPosition == 0)
446 _nav.MoveTo ((XPathNavigator) navigators [--currentPosition]);
447 // Current.MoveTo (_nav);
451 public override bool ReverseAxis {
455 public override int Count {
457 if (navigators == null)
459 return navigators.Count;
464 internal class AncestorOrSelfIterator : SimpleIterator
467 ArrayList navigators;
468 XPathNavigator startPosition;
470 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
472 startPosition = iter.Current.Clone ();
475 private AncestorOrSelfIterator (AncestorOrSelfIterator other)
478 startPosition = other.startPosition;
479 if (other.navigators != null)
480 navigators = (ArrayList) other.navigators.Clone ();
481 currentPosition = other.currentPosition;
484 public override XPathNodeIterator Clone ()
486 return new AncestorOrSelfIterator (this);
489 private void CollectResults ()
491 navigators = new ArrayList ();
493 XPathNavigator ancestors = startPosition.Clone ();
494 if (!ancestors.MoveToParent ())
496 while (ancestors.NodeType != XPathNodeType.Root) {
497 navigators.Add (ancestors.Clone ());
498 ancestors.MoveToParent ();
500 currentPosition = navigators.Count;
503 public override bool MoveNextCore ()
505 if (navigators == null) {
507 if (startPosition.NodeType != XPathNodeType.Root) {
508 // First time it returns Root
510 // Current.MoveTo (_nav);
514 if (currentPosition == -1)
516 if (currentPosition-- == 0) {
517 _nav.MoveTo (startPosition);
518 // Current.MoveTo (_nav);
519 return true; // returns self.
521 _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
522 // Current.MoveTo (_nav);
526 public override bool ReverseAxis {
530 public override int Count {
532 if (navigators == null)
534 return navigators.Count + 1;
539 internal class DescendantIterator : SimpleIterator
542 private bool _finished;
544 public DescendantIterator (BaseIterator iter) : base (iter) {}
546 private DescendantIterator (DescendantIterator other) : base (other, true)
548 _depth = other._depth;
549 _finished = other._finished;
552 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
554 public override bool MoveNextCore ()
559 if (_nav.MoveToFirstChild ())
562 // Current.MoveTo (_nav);
567 if (_nav.MoveToNext ())
569 // Current.MoveTo (_nav);
572 if (!_nav.MoveToParent ()) // should NEVER fail!
573 throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
581 internal class DescendantOrSelfIterator : SimpleIterator
584 private bool _finished;
586 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
588 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
590 _depth = other._depth;
593 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
595 public override bool MoveNextCore ()
600 if (CurrentPosition == 0)
603 // Current.MoveTo (_nav);
606 if (_nav.MoveToFirstChild ())
609 // Current.MoveTo (_nav);
614 if (_nav.MoveToNext ())
616 // Current.MoveTo (_nav);
619 if (!_nav.MoveToParent ()) // should NEVER fail!
620 throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
628 internal class FollowingIterator : SimpleIterator
630 private bool _finished = false;
631 public FollowingIterator (BaseIterator iter) : base (iter) {}
632 private FollowingIterator (FollowingIterator other) : base (other, true) {}
633 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
634 public override bool MoveNextCore ()
638 bool checkChildren = true;
639 if (CurrentPosition == 0)
641 checkChildren = false;
642 switch (_nav.NodeType) {
643 case XPathNodeType.Attribute:
644 case XPathNodeType.Namespace:
645 _nav.MoveToParent ();
646 checkChildren = true;
649 if (_nav.MoveToNext ())
651 // Current.MoveTo (_nav);
654 while (_nav.MoveToParent ()) {
655 if (_nav.MoveToNext ()) {
656 // Current.MoveTo (_nav);
666 if (_nav.MoveToFirstChild ())
668 // Current.MoveTo (_nav);
673 if (_nav.MoveToNext ())
675 // Current.MoveTo (_nav);
679 while (_nav.MoveToParent ());
686 internal class PrecedingIterator : SimpleIterator
690 XPathNavigator startPosition;
692 public PrecedingIterator (BaseIterator iter) : base (iter)
694 startPosition = iter.Current.Clone ();
696 private PrecedingIterator (PrecedingIterator other) : base (other, true)
698 startPosition = other.startPosition;
699 started = other.started;
700 finished = other.finished;
702 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
703 public override bool MoveNextCore ()
713 while (!_nav.MoveToFirstChild ()) {
714 while (!_nav.MoveToNext ()) {
715 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
722 if (_nav.IsDescendant (startPosition))
727 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
728 // Note that if _nav contains only 1 node, it won't be Same.
732 // Current.MoveTo (_nav);
736 public override bool ReverseAxis {
741 internal class NamespaceIterator : SimpleIterator
743 public NamespaceIterator (BaseIterator iter) : base (iter) {}
744 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
745 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
746 public override bool MoveNextCore ()
748 if (CurrentPosition == 0)
750 if (_nav.MoveToFirstNamespace ())
752 // Current.MoveTo (_nav);
756 else if (_nav.MoveToNextNamespace ())
758 // Current.MoveTo (_nav);
765 internal class AttributeIterator : SimpleIterator
767 public AttributeIterator (BaseIterator iter) : base (iter) {}
768 private AttributeIterator (AttributeIterator other) : base (other, true) {}
769 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
770 public override bool MoveNextCore ()
772 if (CurrentPosition == 0)
774 if (_nav.MoveToFirstAttribute ())
776 // Current.MoveTo (_nav);
780 else if (_nav.MoveToNextAttribute ())
782 // Current.MoveTo (_nav);
789 internal class AxisIterator : BaseIterator
791 private BaseIterator _iter;
792 private NodeTest _test;
795 //XPathNodeType matchType;
797 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter.NamespaceManager)
801 //test.GetInfo (out name, out ns, out matchType, NamespaceManager);
803 // name = Current.NameTable.Add (name);
806 // ns = Current.NameTable.Add (ns);
809 private AxisIterator (AxisIterator other) : base (other)
811 _iter = (BaseIterator) other._iter.Clone ();
815 //matchType = other.matchType;
817 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
819 public override bool MoveNextCore ()
821 while (_iter.MoveNext ())
823 if (_test.Match (NamespaceManager, _iter.Current))
830 public override XPathNavigator Current { get { return CurrentPosition == 0 ? null : _iter.Current; }}
832 public override bool ReverseAxis {
833 get { return _iter.ReverseAxis; }
837 internal class SimpleSlashIterator : BaseIterator
839 private NodeSet _expr;
840 private BaseIterator _left, _right;
841 private XPathNavigator _current;
843 public SimpleSlashIterator (BaseIterator left, NodeSet expr)
844 : base (left.NamespaceManager)
850 private SimpleSlashIterator (SimpleSlashIterator other)
854 _left = (BaseIterator) other._left.Clone ();
855 if (other._right != null)
856 _right = (BaseIterator) other._right.Clone ();
859 public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
861 public override bool MoveNextCore ()
863 while (_right == null || !_right.MoveNext ()) {
864 if (!_left.MoveNext ())
866 _right = _expr.EvaluateNodeSet (_left);
868 if (_current == null)
869 _current = _right.Current.Clone ();
871 if (! _current.MoveTo (_right.Current) )
872 _current = _right.Current.Clone ();
876 public override XPathNavigator Current {
877 get { return _current; }
881 internal class SortedIterator : BaseIterator
885 public SortedIterator (BaseIterator iter) : base (iter.NamespaceManager)
887 list = new ArrayList ();
888 while (iter.MoveNext ())
889 list.Add (iter.Current.Clone ());
894 XPathNavigator prev = (XPathNavigator) list [0];
895 list.Sort (XPathNavigatorComparer.Instance);
896 for (int i = 1; i < list.Count; i++) {
897 XPathNavigator n = (XPathNavigator) list [i];
898 if (prev.IsSamePosition (n)) {
907 public SortedIterator (SortedIterator other) : base (other)
909 this.list = other.list;
910 SetPosition (other.CurrentPosition);
913 public override XPathNodeIterator Clone () { return new SortedIterator (this); }
915 public override bool MoveNextCore ()
917 return CurrentPosition < list.Count;
920 public override XPathNavigator Current {
921 get { return CurrentPosition == 0 ? null : (XPathNavigator) list [CurrentPosition - 1]; }
924 public override int Count {
925 get { return list.Count; }
929 // NOTE: it is *not* sorted. Do not directly use it without checking sorting requirement.
930 internal class SlashIterator : BaseIterator
932 private BaseIterator _iterLeft;
933 private BaseIterator _iterRight;
934 private NodeSet _expr;
935 SortedList _iterList;
937 BaseIterator _nextIterRight;
939 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter.NamespaceManager)
945 private SlashIterator (SlashIterator other) : base (other)
947 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
948 if (other._iterRight != null)
949 _iterRight = (BaseIterator) other._iterRight.Clone ();
951 if (other._iterList != null)
952 _iterList = (SortedList) other._iterList.Clone ();
953 _finished = other._finished;
954 if (other._nextIterRight != null)
955 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
957 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
959 public override bool MoveNextCore ()
964 if (_iterRight == null) { // First time
965 if (!_iterLeft.MoveNext ())
967 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
968 _iterList = new SortedList (XPathIteratorComparer.Instance);
972 while (!_iterRight.MoveNext ()) {
973 if (_iterList.Count > 0) {
974 int last = _iterList.Count - 1;
975 _iterRight = (BaseIterator) _iterList.GetByIndex (last);
976 _iterList.RemoveAt (last);
978 } else if (_nextIterRight != null) {
979 _iterRight = _nextIterRight;
980 _nextIterRight = null;
982 } else if (!_iterLeft.MoveNext ()) {
987 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
992 if (_nextIterRight == null) {
993 bool noMoreNext = false;
994 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
995 if(_iterLeft.MoveNext ())
996 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
1003 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
1005 if (_nextIterRight != null) {
1006 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
1007 case XmlNodeOrder.After:
1008 _iterList [_iterRight] = _iterRight;
1009 _iterRight = _nextIterRight;
1010 _nextIterRight = null;
1013 case XmlNodeOrder.Same:
1014 if (!_nextIterRight.MoveNext ())
1015 _nextIterRight = null;
1018 int last = _iterList.Count;
1019 _iterList [_nextIterRight] = _nextIterRight;
1020 if (last != _iterList.Count) {
1021 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
1022 _iterList.RemoveAt (last);
1035 public override XPathNavigator Current {
1037 return (CurrentPosition == 0) ? null : _iterRight.Current;
1042 internal class PredicateIterator : BaseIterator
1044 private BaseIterator _iter;
1045 private Expression _pred;
1046 private XPathResultType resType;
1047 private bool finished;
1049 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter.NamespaceManager)
1053 resType = pred.GetReturnType (iter);
1056 private PredicateIterator (PredicateIterator other) : base (other)
1058 _iter = (BaseIterator) other._iter.Clone ();
1059 _pred = other._pred;
1060 resType = other.resType;
1061 finished = other.finished;
1063 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1065 public override bool MoveNextCore ()
1069 while (_iter.MoveNext ())
1072 case XPathResultType.Number:
1073 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1076 case XPathResultType.Any: {
1077 object result = _pred.Evaluate (_iter);
1078 if (result is double)
1080 if ((double) result != _iter.ComparablePosition)
1083 else if (!XPathFunctions.ToBoolean (result))
1088 if (!_pred.EvaluateBoolean (_iter))
1098 public override XPathNavigator Current {
1099 get { return CurrentPosition == 0 ? null : _iter.Current; }}
1100 public override bool ReverseAxis {
1101 get { return _iter.ReverseAxis; }
1103 public override string ToString () { return _iter.GetType ().FullName; }
1106 internal class ListIterator : BaseIterator
1108 private IList _list;
1110 public ListIterator (BaseIterator iter, IList list) : base (iter.NamespaceManager)
1115 public ListIterator (IList list, NSResolver nsm) : base (nsm)
1120 private ListIterator (ListIterator other) : base (other)
1122 _list = other._list;
1124 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1126 public override bool MoveNextCore ()
1128 if (CurrentPosition >= _list.Count)
1132 public override XPathNavigator Current {
1134 if (_list.Count == 0 || CurrentPosition == 0)
1136 return (XPathNavigator) _list [CurrentPosition - 1];
1140 public override int Count { get { return _list.Count; } }
1144 internal class UnionIterator : BaseIterator
1146 private BaseIterator _left, _right;
1147 private bool keepLeft;
1148 private bool keepRight;
1149 XPathNavigator _current;
1151 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1157 private UnionIterator (UnionIterator other) : base (other)
1159 _left = (BaseIterator) other._left.Clone ();
1160 _right = (BaseIterator) other._right.Clone ();
1161 keepLeft = other.keepLeft;
1162 keepRight = other.keepRight;
1163 if (other._current != null)
1164 _current = other._current.Clone ();
1166 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1168 public override bool MoveNextCore ()
1171 keepLeft = _left.MoveNext ();
1173 keepRight = _right.MoveNext ();
1175 if (!keepLeft && !keepRight)
1182 } else if (!keepLeft) {
1184 SetCurrent (_right);
1188 switch (_left.Current.ComparePosition (_right.Current)) {
1189 case XmlNodeOrder.Same:
1190 // consume both. i.e. don't output duplicate result.
1191 keepLeft = keepRight = false;
1192 SetCurrent (_right);
1194 case XmlNodeOrder.Before:
1195 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1199 case XmlNodeOrder.After:
1201 SetCurrent (_right);
1204 throw new InvalidOperationException ("Should not happen.");
1208 private void SetCurrent (XPathNodeIterator iter)
1210 if (_current == null)
1211 _current = iter.Current.Clone ();
1213 if (! _current.MoveTo (iter.Current) )
1214 _current = iter.Current.Clone ();
1217 public override XPathNavigator Current
1219 get { return CurrentPosition > 0 ? _current : null; }
1223 internal class OrderedIterator : BaseIterator
1229 public OrderedIterator (BaseIterator iter)
1230 : base (iter.NamespaceManager)
1232 // if (iter.Ordered)
1234 // this.iter = iter;
1237 list = new ArrayList ();
1238 while (iter.MoveNext ())
1239 list.Add (iter.Current);
1240 list.Sort (XPathNavigatorComparer.Instance);
1244 private OrderedIterator (OrderedIterator other, bool dummy)
1247 if (other.iter != null)
1248 iter = (BaseIterator) other.iter.Clone ();
1250 index = other.index;
1253 public override XPathNodeIterator Clone ()
1255 return new OrderedIterator (this);
1258 public override bool MoveNextCore ()
1261 return iter.MoveNext ();
1262 else if (index++ < list.Count)
1268 public override XPathNavigator Current {
1269 get { return iter != null ? iter.Current : index < 0 ? null : (XPathNavigator) list [index]; }