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 while (ancestors.NodeType != XPathNodeType.Root && ancestors.MoveToParent ())
495 navigators.Add (ancestors.Clone ());
496 currentPosition = navigators.Count;
499 public override bool MoveNextCore ()
501 if (navigators == null)
503 if (currentPosition == -1)
505 if (currentPosition-- == 0) {
506 _nav.MoveTo (startPosition);
507 // Current.MoveTo (_nav);
508 return true; // returns self.
510 _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
511 // Current.MoveTo (_nav);
515 public override bool ReverseAxis {
519 public override int Count {
521 if (navigators == null)
523 return navigators.Count + 1;
528 internal class DescendantIterator : SimpleIterator
531 private bool _finished;
533 public DescendantIterator (BaseIterator iter) : base (iter) {}
535 private DescendantIterator (DescendantIterator other) : base (other, true)
537 _depth = other._depth;
538 _finished = other._finished;
541 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
543 public override bool MoveNextCore ()
548 if (_nav.MoveToFirstChild ())
551 // Current.MoveTo (_nav);
556 if (_nav.MoveToNext ())
558 // Current.MoveTo (_nav);
561 if (!_nav.MoveToParent ()) // should NEVER fail!
562 throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
570 internal class DescendantOrSelfIterator : SimpleIterator
573 private bool _finished;
575 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
577 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
579 _depth = other._depth;
582 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
584 public override bool MoveNextCore ()
589 if (CurrentPosition == 0)
592 // Current.MoveTo (_nav);
595 if (_nav.MoveToFirstChild ())
598 // Current.MoveTo (_nav);
603 if (_nav.MoveToNext ())
605 // Current.MoveTo (_nav);
608 if (!_nav.MoveToParent ()) // should NEVER fail!
609 throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
617 internal class FollowingIterator : SimpleIterator
619 private bool _finished = false;
620 public FollowingIterator (BaseIterator iter) : base (iter) {}
621 private FollowingIterator (FollowingIterator other) : base (other, true) {}
622 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
623 public override bool MoveNextCore ()
627 bool checkChildren = true;
628 if (CurrentPosition == 0)
630 checkChildren = false;
631 switch (_nav.NodeType) {
632 case XPathNodeType.Attribute:
633 case XPathNodeType.Namespace:
634 _nav.MoveToParent ();
635 checkChildren = true;
638 if (_nav.MoveToNext ())
640 // Current.MoveTo (_nav);
643 while (_nav.MoveToParent ()) {
644 if (_nav.MoveToNext ()) {
645 // Current.MoveTo (_nav);
655 if (_nav.MoveToFirstChild ())
657 // Current.MoveTo (_nav);
662 if (_nav.MoveToNext ())
664 // Current.MoveTo (_nav);
668 while (_nav.MoveToParent ());
675 internal class PrecedingIterator : SimpleIterator
679 XPathNavigator startPosition;
681 public PrecedingIterator (BaseIterator iter) : base (iter)
683 startPosition = iter.Current.Clone ();
685 private PrecedingIterator (PrecedingIterator other) : base (other, true)
687 startPosition = other.startPosition;
688 started = other.started;
689 finished = other.finished;
691 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
692 public override bool MoveNextCore ()
702 while (!_nav.MoveToFirstChild ()) {
703 while (!_nav.MoveToNext ()) {
704 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
711 if (_nav.IsDescendant (startPosition))
716 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
717 // Note that if _nav contains only 1 node, it won't be Same.
721 // Current.MoveTo (_nav);
725 public override bool ReverseAxis {
730 internal class NamespaceIterator : SimpleIterator
732 public NamespaceIterator (BaseIterator iter) : base (iter) {}
733 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
734 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
735 public override bool MoveNextCore ()
737 if (CurrentPosition == 0)
739 if (_nav.MoveToFirstNamespace ())
741 // Current.MoveTo (_nav);
745 else if (_nav.MoveToNextNamespace ())
747 // Current.MoveTo (_nav);
754 internal class AttributeIterator : SimpleIterator
756 public AttributeIterator (BaseIterator iter) : base (iter) {}
757 private AttributeIterator (AttributeIterator other) : base (other, true) {}
758 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
759 public override bool MoveNextCore ()
761 if (CurrentPosition == 0)
763 if (_nav.MoveToFirstAttribute ())
765 // Current.MoveTo (_nav);
769 else if (_nav.MoveToNextAttribute ())
771 // Current.MoveTo (_nav);
778 internal class AxisIterator : BaseIterator
780 private BaseIterator _iter;
781 private NodeTest _test;
784 //XPathNodeType matchType;
786 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter.NamespaceManager)
790 //test.GetInfo (out name, out ns, out matchType, NamespaceManager);
792 // name = Current.NameTable.Add (name);
795 // ns = Current.NameTable.Add (ns);
798 private AxisIterator (AxisIterator other) : base (other)
800 _iter = (BaseIterator) other._iter.Clone ();
804 //matchType = other.matchType;
806 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
808 public override bool MoveNextCore ()
810 while (_iter.MoveNext ())
812 if (_test.Match (NamespaceManager, _iter.Current))
819 public override XPathNavigator Current { get { return CurrentPosition == 0 ? null : _iter.Current; }}
821 public override bool ReverseAxis {
822 get { return _iter.ReverseAxis; }
826 internal class SimpleSlashIterator : BaseIterator
828 private NodeSet _expr;
829 private BaseIterator _left, _right;
830 private XPathNavigator _current;
832 public SimpleSlashIterator (BaseIterator left, NodeSet expr)
833 : base (left.NamespaceManager)
839 private SimpleSlashIterator (SimpleSlashIterator other)
843 _left = (BaseIterator) other._left.Clone ();
844 if (other._right != null)
845 _right = (BaseIterator) other._right.Clone ();
848 public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
850 public override bool MoveNextCore ()
852 while (_right == null || !_right.MoveNext ()) {
853 if (!_left.MoveNext ())
855 _right = _expr.EvaluateNodeSet (_left);
857 if (_current == null)
858 _current = _right.Current.Clone ();
860 if (! _current.MoveTo (_right.Current) )
861 _current = _right.Current.Clone ();
865 public override XPathNavigator Current {
866 get { return _current; }
870 internal class SortedIterator : BaseIterator
874 public SortedIterator (BaseIterator iter) : base (iter.NamespaceManager)
876 list = new ArrayList ();
877 while (iter.MoveNext ())
878 list.Add (iter.Current.Clone ());
883 XPathNavigator prev = (XPathNavigator) list [0];
884 list.Sort (XPathNavigatorComparer.Instance);
885 for (int i = 1; i < list.Count; i++) {
886 XPathNavigator n = (XPathNavigator) list [i];
887 if (prev.IsSamePosition (n)) {
896 public SortedIterator (SortedIterator other) : base (other)
898 this.list = other.list;
899 SetPosition (other.CurrentPosition);
902 public override XPathNodeIterator Clone () { return new SortedIterator (this); }
904 public override bool MoveNextCore ()
906 return CurrentPosition < list.Count;
909 public override XPathNavigator Current {
910 get { return CurrentPosition == 0 ? null : (XPathNavigator) list [CurrentPosition - 1]; }
913 public override int Count {
914 get { return list.Count; }
918 // NOTE: it is *not* sorted. Do not directly use it without checking sorting requirement.
919 internal class SlashIterator : BaseIterator
921 private BaseIterator _iterLeft;
922 private BaseIterator _iterRight;
923 private NodeSet _expr;
924 SortedList _iterList;
926 BaseIterator _nextIterRight;
928 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter.NamespaceManager)
934 private SlashIterator (SlashIterator other) : base (other)
936 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
937 if (other._iterRight != null)
938 _iterRight = (BaseIterator) other._iterRight.Clone ();
940 if (other._iterList != null)
941 _iterList = (SortedList) other._iterList.Clone ();
942 _finished = other._finished;
943 if (other._nextIterRight != null)
944 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
946 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
948 public override bool MoveNextCore ()
953 if (_iterRight == null) { // First time
954 if (!_iterLeft.MoveNext ())
956 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
957 _iterList = new SortedList (XPathIteratorComparer.Instance);
961 while (!_iterRight.MoveNext ()) {
962 if (_iterList.Count > 0) {
963 int last = _iterList.Count - 1;
964 _iterRight = (BaseIterator) _iterList.GetByIndex (last);
965 _iterList.RemoveAt (last);
967 } else if (_nextIterRight != null) {
968 _iterRight = _nextIterRight;
969 _nextIterRight = null;
971 } else if (!_iterLeft.MoveNext ()) {
976 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
981 if (_nextIterRight == null) {
982 bool noMoreNext = false;
983 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
984 if(_iterLeft.MoveNext ())
985 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
992 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
994 if (_nextIterRight != null) {
995 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
996 case XmlNodeOrder.After:
997 _iterList [_iterRight] = _iterRight;
998 _iterRight = _nextIterRight;
999 _nextIterRight = null;
1002 case XmlNodeOrder.Same:
1003 if (!_nextIterRight.MoveNext ())
1004 _nextIterRight = null;
1007 int last = _iterList.Count;
1008 _iterList [_nextIterRight] = _nextIterRight;
1009 if (last != _iterList.Count) {
1010 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
1011 _iterList.RemoveAt (last);
1024 public override XPathNavigator Current {
1026 return (CurrentPosition == 0) ? null : _iterRight.Current;
1031 internal class PredicateIterator : BaseIterator
1033 private BaseIterator _iter;
1034 private Expression _pred;
1035 private XPathResultType resType;
1036 private bool finished;
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;
1050 finished = other.finished;
1052 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1054 public override bool MoveNextCore ()
1058 while (_iter.MoveNext ())
1061 case XPathResultType.Number:
1062 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1065 case XPathResultType.Any: {
1066 object result = _pred.Evaluate (_iter);
1067 if (result is double)
1069 if ((double) result != _iter.ComparablePosition)
1072 else if (!XPathFunctions.ToBoolean (result))
1077 if (!_pred.EvaluateBoolean (_iter))
1087 public override XPathNavigator Current {
1088 get { return CurrentPosition == 0 ? null : _iter.Current; }}
1089 public override bool ReverseAxis {
1090 get { return _iter.ReverseAxis; }
1092 public override string ToString () { return _iter.GetType ().FullName; }
1095 internal class ListIterator : BaseIterator
1097 private IList _list;
1099 public ListIterator (BaseIterator iter, IList list) : base (iter.NamespaceManager)
1104 public ListIterator (IList list, NSResolver nsm) : base (nsm)
1109 private ListIterator (ListIterator other) : base (other)
1111 _list = other._list;
1113 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1115 public override bool MoveNextCore ()
1117 if (CurrentPosition >= _list.Count)
1121 public override XPathNavigator Current {
1123 if (_list.Count == 0 || CurrentPosition == 0)
1125 return (XPathNavigator) _list [CurrentPosition - 1];
1129 public override int Count { get { return _list.Count; } }
1133 internal class UnionIterator : BaseIterator
1135 private BaseIterator _left, _right;
1136 private bool keepLeft;
1137 private bool keepRight;
1138 XPathNavigator _current;
1140 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1146 private UnionIterator (UnionIterator other) : base (other)
1148 _left = (BaseIterator) other._left.Clone ();
1149 _right = (BaseIterator) other._right.Clone ();
1150 keepLeft = other.keepLeft;
1151 keepRight = other.keepRight;
1152 if (other._current != null)
1153 _current = other._current.Clone ();
1155 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1157 public override bool MoveNextCore ()
1160 keepLeft = _left.MoveNext ();
1162 keepRight = _right.MoveNext ();
1164 if (!keepLeft && !keepRight)
1171 } else if (!keepLeft) {
1173 SetCurrent (_right);
1177 switch (_left.Current.ComparePosition (_right.Current)) {
1178 case XmlNodeOrder.Same:
1179 // consume both. i.e. don't output duplicate result.
1180 keepLeft = keepRight = false;
1181 SetCurrent (_right);
1183 case XmlNodeOrder.Before:
1184 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1188 case XmlNodeOrder.After:
1190 SetCurrent (_right);
1193 throw new InvalidOperationException ("Should not happen.");
1197 private void SetCurrent (XPathNodeIterator iter)
1199 if (_current == null)
1200 _current = iter.Current.Clone ();
1202 if (! _current.MoveTo (iter.Current) )
1203 _current = iter.Current.Clone ();
1206 public override XPathNavigator Current
1208 get { return CurrentPosition > 0 ? _current : null; }
1212 internal class OrderedIterator : BaseIterator
1218 public OrderedIterator (BaseIterator iter)
1219 : base (iter.NamespaceManager)
1221 // if (iter.Ordered)
1223 // this.iter = iter;
1226 list = new ArrayList ();
1227 while (iter.MoveNext ())
1228 list.Add (iter.Current);
1229 list.Sort (XPathNavigatorComparer.Instance);
1233 private OrderedIterator (OrderedIterator other, bool dummy)
1236 if (other.iter != null)
1237 iter = (BaseIterator) other.iter.Clone ();
1239 index = other.index;
1242 public override XPathNodeIterator Clone ()
1244 return new OrderedIterator (this);
1247 public override bool MoveNextCore ()
1250 return iter.MoveNext ();
1251 else if (index++ < list.Count)
1257 public override XPathNavigator Current {
1258 get { return iter != null ? iter.Current : index < 0 ? null : (XPathNavigator) list [index]; }