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 using System.Collections;
15 using System.Xml.XPath;
18 namespace System.Xml.XPath
20 internal abstract class BaseIterator : XPathNodeIterator
22 private XmlNamespaceManager _nsm;
23 protected bool _needClone = true; // TODO: use this field in practice.
25 internal BaseIterator (BaseIterator other)
29 internal BaseIterator (XmlNamespaceManager nsm)
34 public XmlNamespaceManager NamespaceManager
40 public virtual bool ReverseAxis {
44 public abstract bool RequireSorting { get; }
46 public virtual int ComparablePosition {
49 int diff = Count - CurrentPosition + 1;
50 return diff < 1 ? 1 : diff;
53 return CurrentPosition;
57 public override string ToString ()
60 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
62 return this.GetType().ToString () + "[" + CurrentPosition + "]";
66 internal abstract class SimpleIterator : BaseIterator
68 protected readonly BaseIterator _iter;
69 protected readonly XPathNavigator _nav;
70 protected XPathNavigator _current;
73 public SimpleIterator (BaseIterator iter) : base (iter)
76 _nav = iter.Current.Clone ();
77 _current = _nav.Clone ();
79 protected SimpleIterator (SimpleIterator other) : base (other)
81 if (other._nav == null)
82 _iter = (BaseIterator) other._iter.Clone ();
84 _nav = other._nav.Clone ();
86 _current = other._current.Clone ();
88 public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
91 _current = nav.Clone ();
94 public override XPathNavigator Current { get { return _current; }}
95 public override int CurrentPosition { get { return _pos; }}
98 internal class SelfIterator : SimpleIterator
100 public SelfIterator (BaseIterator iter) : base (iter) {}
101 public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
102 protected SelfIterator (SelfIterator other) : base (other) {}
103 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
104 public override bool MoveNext ()
109 _current = _needClone ? _nav.Clone () : _nav;
115 public override bool RequireSorting { get { return false; } }
118 internal class NullIterator : SelfIterator
120 public NullIterator (BaseIterator iter) : base (iter) {}
121 public NullIterator (XPathNavigator nav) : this (nav, null) {}
122 public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
123 protected NullIterator (NullIterator other) : base (other) {}
124 public override XPathNodeIterator Clone () { return new NullIterator (this); }
125 public override bool MoveNext ()
131 internal class ParensIterator : BaseIterator
134 public ParensIterator (BaseIterator iter) : base (iter)
138 protected ParensIterator (ParensIterator other) : base (other)
140 _iter = (BaseIterator) other._iter.Clone ();
142 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
143 public override bool MoveNext ()
145 return _iter.MoveNext ();
148 public override XPathNavigator Current { get { return _iter.Current; }}
149 public override int CurrentPosition { get { return _iter.CurrentPosition; } }
151 public override bool RequireSorting { get { return _iter.RequireSorting; } }
153 public override int Count { get { return _iter.Count; } }
156 internal class ParentIterator : SimpleIterator
158 public ParentIterator (BaseIterator iter) : base (iter) {}
159 protected ParentIterator (ParentIterator other) : base (other) {}
160 public ParentIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
161 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
162 public override bool MoveNext ()
164 if (_pos == 0 && _nav.MoveToParent ())
167 _current = _needClone ? _nav.Clone () : _nav;
173 public override bool RequireSorting { get { return true; } }
176 internal class ChildIterator : SimpleIterator
178 public ChildIterator (BaseIterator iter) : base (iter) {}
179 protected ChildIterator (ChildIterator other) : base (other) {}
180 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
181 public override bool MoveNext ()
183 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
186 // This clone cannot be omitted
187 _current = _nav.Clone ();
192 public override bool RequireSorting { get { return false; } }
195 internal class FollowingSiblingIterator : SimpleIterator
197 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
198 protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
199 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
200 public override bool MoveNext ()
202 switch (_nav.NodeType) {
203 case XPathNodeType.Attribute:
204 case XPathNodeType.Namespace:
205 // They have no siblings.
208 if (_nav.MoveToNext ())
211 // This clone cannot be omitted
212 _current = _nav.Clone ();
218 public override bool RequireSorting { get { return false; } }
221 internal class PrecedingSiblingIterator : SimpleIterator
225 XPathNavigator startPosition;
227 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
229 startPosition = iter.Current.Clone ();
230 _current = startPosition.Clone ();
232 protected PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other)
234 startPosition = other.startPosition;
235 started = other.started;
236 finished = other.finished;
237 _current = other._current.Clone ();
240 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
241 public override bool MoveNext ()
247 switch (_nav.NodeType) {
248 case XPathNodeType.Attribute:
249 case XPathNodeType.Namespace:
250 // They have no siblings.
256 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Same) {
258 // This clone cannot be omitted
259 _current = _nav.Clone ();
263 if (!_nav.MoveToNext ()) {
268 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
269 // Note that if _nav contains only 1 node, it won't be Same.
274 // This clone cannot be omitted
275 _current = _nav.Clone ();
279 public override bool ReverseAxis {
283 public override bool RequireSorting { get { return true; } }
286 internal class AncestorIterator : SimpleIterator
290 ArrayList positions = new ArrayList ();
291 XPathNavigator startPosition;
293 public AncestorIterator (BaseIterator iter) : base (iter)
295 startPosition = iter.Current.Clone ();
296 _current = startPosition.Clone ();
298 protected AncestorIterator (AncestorIterator other) : base (other)
300 startPosition = other.startPosition;
301 started = other.started;
302 finished = other.finished;
303 positions = (ArrayList) other.positions.Clone ();
304 nextDepth = other.nextDepth;
305 _current = other._current.Clone ();
307 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
308 public override bool MoveNext ()
314 // This clone cannot be omitted
315 XPathNavigator ancestors = startPosition.Clone ();
316 ancestors.MoveToParent ();
317 _nav.MoveToParent ();
318 while (ancestors.NodeType != XPathNodeType.Root) {
321 while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
326 ancestors.MoveToParent ();
327 _nav.MoveToParent ();
331 positions.Reverse ();
333 if (startPosition.NodeType != XPathNodeType.Root) {
334 // First time it returns Root
336 // This clone cannot be omitted
337 _current = _nav.Clone ();
341 // Don't worry about node type of start position, like AncestorOrSelf.
342 // It should be Element or Root.
343 if (nextDepth < positions.Count) {
344 int thisTimePos = (int) positions [nextDepth];
345 _nav.MoveToFirstChild ();
346 for (int i = 0; i < thisTimePos; i++)
350 // This clone cannot be omitted
351 _current = _nav.Clone ();
358 public override bool ReverseAxis {
362 public override bool RequireSorting { get { return true; } }
364 public override int Count { get { return positions.Count; } }
367 internal class AncestorOrSelfIterator : SimpleIterator
371 ArrayList positions = new ArrayList ();
372 XPathNavigator startPosition;
375 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
377 startPosition = iter.Current.Clone ();
378 _current = startPosition.Clone ();
380 protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other)
382 startPosition = other.startPosition;
383 started = other.started;
384 finished = other.finished;
385 positions = (ArrayList) other.positions.Clone ();
386 nextDepth = other.nextDepth;
387 _current = other._current.Clone ();
389 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
390 public override bool MoveNext ()
392 bool initialIteration = false;
396 initialIteration = true;
398 // This clone cannot be omitted
399 XPathNavigator ancestors = startPosition.Clone ();
403 while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
408 ancestors.MoveToParent ();
409 _nav.MoveToParent ();
410 } while (ancestors.NodeType != XPathNodeType.Root);
411 positions.Reverse ();
413 if (initialIteration && startPosition.NodeType != XPathNodeType.Root) {
414 // This clone cannot be omitted
415 _current = _nav.Clone ();
417 } else if (nextDepth + 1 == positions.Count) {
420 _nav.MoveTo (startPosition);
421 // This clone cannot be omitted
422 _current = _nav.Clone ();
425 else if (nextDepth < positions.Count) {
426 int thisTimePos = (int) positions [nextDepth];
427 _nav.MoveToFirstChild ();
428 for (int i = 0; i < thisTimePos; i++)
432 // This clone cannot be omitted
433 _current = _nav.Clone ();
440 public override bool ReverseAxis {
444 public override bool RequireSorting { get { return true; } }
446 public override int Count { get { return positions.Count; } }
449 internal class DescendantIterator : SimpleIterator
451 protected int _depth;
452 private bool _finished;
454 public DescendantIterator (BaseIterator iter) : base (iter) {}
456 protected DescendantIterator (DescendantIterator other) : base (other)
458 _depth = other._depth;
459 _current = other._current.Clone ();
462 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
464 public override bool MoveNext ()
469 if (_nav.MoveToFirstChild ())
473 // This clone cannot be omitted
474 _current = _nav.Clone ();
479 if (_nav.MoveToNext ())
482 // This clone cannot be omitted
483 _current = _nav.Clone ();
486 if (!_nav.MoveToParent ()) // should NEVER fail!
487 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
494 public override bool RequireSorting { get { return false; } }
497 internal class DescendantOrSelfIterator : SimpleIterator
499 protected int _depth;
500 private bool _finished;
502 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
504 protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
506 _depth = other._depth;
507 _current = other._current.Clone ();
510 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
512 public override bool MoveNext ()
521 // This clone cannot be omitted
522 _current = _nav.Clone ();
525 if (_nav.MoveToFirstChild ())
529 // This clone cannot be omitted
530 _current = _nav.Clone ();
535 if (_nav.MoveToNext ())
538 // This clone cannot be omitted
539 _current = _nav.Clone ();
542 if (!_nav.MoveToParent ()) // should NEVER fail!
543 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
550 public override bool RequireSorting { get { return false; } }
553 internal class FollowingIterator : SimpleIterator
555 private bool _finished = false;
556 public FollowingIterator (BaseIterator iter) : base (iter) {}
557 protected FollowingIterator (FollowingIterator other) : base (other) {}
558 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
559 public override bool MoveNext ()
565 if (_nav.MoveToNext ())
568 // This clone cannot be omitted
569 _current = _nav.Clone ();
572 while (_nav.MoveToParent ()) {
573 if (_nav.MoveToNext ()) {
575 // This clone cannot be omitted
576 _current = _nav.Clone ();
584 if (_nav.MoveToFirstChild ())
587 // This clone cannot be omitted
588 _current = _nav.Clone ();
593 if (_nav.MoveToNext ())
596 // This clone cannot be omitted
597 _current = _nav.Clone ();
601 while (_nav.MoveToParent ());
607 public override bool RequireSorting { get { return false; } }
610 internal class PrecedingIterator : SimpleIterator
614 XPathNavigator startPosition;
616 public PrecedingIterator (BaseIterator iter) : base (iter)
618 startPosition = iter.Current.Clone ();
619 _current = startPosition.Clone ();
621 protected PrecedingIterator (PrecedingIterator other) : base (other)
623 startPosition = other.startPosition;
624 started = other.started;
625 finished = other.finished;
626 _current = other._current.Clone ();
628 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
629 public override bool MoveNext ()
639 while (!_nav.MoveToFirstChild ()) {
640 while (!_nav.MoveToNext ()) {
641 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
648 if (_nav.IsDescendant (startPosition))
653 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
654 // Note that if _nav contains only 1 node, it won't be Same.
659 // This cannot be omitted
660 _current = _nav.Clone ();
664 public override bool ReverseAxis {
668 public override bool RequireSorting { get { return true; } }
671 internal class NamespaceIterator : SimpleIterator
673 public NamespaceIterator (BaseIterator iter) : base (iter) {}
674 protected NamespaceIterator (NamespaceIterator other) : base (other) {}
675 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
676 public override bool MoveNext ()
680 if (_nav.MoveToFirstNamespace ())
683 // This clone cannot be omitted
684 _current = _nav.Clone ();
688 else if (_nav.MoveToNextNamespace ())
691 // This clone cannot be omitted
692 _current = _nav.Clone ();
698 public override bool ReverseAxis { get { return true; } }
699 public override bool RequireSorting { get { return false; } }
702 internal class AttributeIterator : SimpleIterator
704 public AttributeIterator (BaseIterator iter) : base (iter) {}
705 protected AttributeIterator (AttributeIterator other) : base (other) {}
706 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
707 public override bool MoveNext ()
711 if (_nav.MoveToFirstAttribute ())
714 // This clone cannot be omitted
715 _current = _nav.Clone ();
719 else if (_nav.MoveToNextAttribute ())
722 // This clone cannot be omitted
723 _current = _nav.Clone ();
729 public override bool RequireSorting { get { return false; } }
732 internal class AxisIterator : BaseIterator
734 protected SimpleIterator _iter;
735 protected NodeTest _test;
739 XPathNodeType matchType;
741 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
745 test.GetInfo (out name, out ns, out matchType, NamespaceManager);
747 // name = Current.NameTable.Add (name);
750 // ns = Current.NameTable.Add (ns);
753 protected AxisIterator (AxisIterator other) : base (other)
755 _iter = (SimpleIterator) other._iter.Clone ();
760 matchType = other.matchType;
762 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
764 public override bool MoveNext ()
766 while (_iter.MoveNext ())
768 if (_test.Match (NamespaceManager, Current))
776 public override XPathNavigator Current { get { return _iter.Current; }}
777 public override int CurrentPosition { get { return _pos; }}
781 if (Current.NodeType != matchType && matchType != XPathNodeType.All)
785 return name == null || (object)name == (object)Current.LocalName;
787 return (object)ns == (object)Current.NamespaceURI &&
788 (name == null || (object)name == (object)Current.LocalName);
790 public override bool ReverseAxis {
791 get { return _iter.ReverseAxis; }
794 public override bool RequireSorting { get { return _iter.RequireSorting; } }
797 internal class SlashIterator : BaseIterator
799 protected BaseIterator _iterLeft;
800 protected BaseIterator _iterRight;
801 protected NodeSet _expr;
804 SortedList _iterList;
806 BaseIterator _nextIterRight;
808 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
814 protected SlashIterator (SlashIterator other) : base (other)
816 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
817 if (other._iterRight != null)
818 _iterRight = (BaseIterator) other._iterRight.Clone ();
821 if (other._iterList != null)
822 _iterList = (SortedList) other._iterList.Clone ();
823 if (other._navStore != null)
824 _navStore = (ArrayList) other._navStore.Clone ();
825 _finished = other._finished;
826 if (other._nextIterRight != null)
827 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
829 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
831 public override bool MoveNext ()
835 if (RequireSorting) {
838 if (_navStore.Count == 0) {
844 if (_navStore.Count < _pos) {
849 while (_navStore.Count > _pos) {
850 if (((XPathNavigator) _navStore [_pos]).ComparePosition (
851 (XPathNavigator) _navStore [_pos - 1]) == XmlNodeOrder.Same)
852 _navStore.RemoveAt (_pos);
859 if (_iterRight == null) { // First time
860 if (!_iterLeft.MoveNext ())
862 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
863 _iterList = new SortedList (XPathIteratorComparer.Instance);
867 while (!_iterRight.MoveNext ()) {
868 if (_iterList.Count > 0) {
869 int last = _iterList.Count - 1;
870 BaseIterator tmpIter = (BaseIterator) _iterList.GetByIndex (last);
871 _iterList.RemoveAt (last);
872 switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
873 case XmlNodeOrder.Same:
874 case XmlNodeOrder.Before:
875 _iterRight = tmpIter;
878 _iterRight = tmpIter;
882 } else if (_nextIterRight != null) {
883 _iterRight = _nextIterRight;
884 _nextIterRight = null;
886 } else if (!_iterLeft.MoveNext ()) {
891 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
896 if (_nextIterRight == null) {
897 bool noMoreNext = false;
898 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
899 if(_iterLeft.MoveNext ())
900 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
907 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
909 if (_nextIterRight != null) {
910 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
911 case XmlNodeOrder.After:
912 _iterList.Add (_iterList.Count, _iterRight);
913 _iterRight = _nextIterRight;
914 _nextIterRight = null;
917 case XmlNodeOrder.Same:
918 if (!_nextIterRight.MoveNext ())
919 _nextIterRight = null;
922 int last = _iterList.Count;
924 _iterList.Add (last, _nextIterRight);
925 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
926 _iterList.RemoveAt (last);
940 private void CollectResults ()
942 if (_navStore != null)
944 _navStore = new ArrayList ();
946 while (_iterRight == null || !_iterRight.MoveNext ()) {
947 if (!_iterLeft.MoveNext ()) {
948 _navStore.Sort (XPathNavigatorComparer.Instance);
951 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
953 XPathNavigator nav = _iterRight.Current;
954 _navStore.Add (_needClone ? nav.Clone () : nav);
958 public override XPathNavigator Current {
960 if (_pos <= 0) return null;
961 if (RequireSorting) {
962 return (XPathNavigator) _navStore [_pos - 1];
964 return _iterRight.Current;
968 public override int CurrentPosition { get { return _pos; }}
970 public override bool RequireSorting {
972 return _iterLeft.RequireSorting || _expr.RequireSorting;
976 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
979 internal class PredicateIterator : BaseIterator
981 protected BaseIterator _iter;
982 protected Expression _pred;
984 protected XPathResultType resType;
986 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
990 resType = pred.GetReturnType (iter);
993 protected PredicateIterator (PredicateIterator other) : base (other)
995 _iter = (BaseIterator) other._iter.Clone ();
998 resType = other.resType;
1000 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1002 public override bool MoveNext ()
1004 while (_iter.MoveNext ())
1007 case XPathResultType.Number:
1008 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1011 case XPathResultType.Any: {
1012 object result = _pred.Evaluate (_iter);
1013 if (result is double)
1015 if ((double) result != _iter.ComparablePosition)
1018 else if (!XPathFunctions.ToBoolean (result))
1023 if (!_pred.EvaluateBoolean (_iter))
1033 public override XPathNavigator Current { get { return _iter.Current; }}
1034 public override int CurrentPosition { get { return _pos; }}
1035 public override bool ReverseAxis {
1036 get { return _iter.ReverseAxis; }
1039 public override bool RequireSorting { get { return true; } }
1042 internal class EnumeratorIterator : BaseIterator
1044 protected IEnumerator _enum;
1046 bool _requireSorting;
1048 public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator, bool requireSorting) : base (iter)
1050 if (!(enumerator is ICloneable))
1051 throw new ArgumentException ("Target enumerator must be cloneable.");
1053 _requireSorting = requireSorting;
1056 public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
1058 if (!(enumerator is ICloneable))
1059 throw new ArgumentException ("Target enumerator must be cloneable.");
1061 _requireSorting = requireSorting;
1064 protected EnumeratorIterator (EnumeratorIterator other) : base (other)
1066 ICloneable enumClone = other._enum as ICloneable;
1067 _enum = (IEnumerator) enumClone.Clone ();
1069 _requireSorting = other._requireSorting;
1071 public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
1073 public override bool MoveNext ()
1075 if (!_enum.MoveNext ())
1080 public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
1081 public override int CurrentPosition { get { return _pos; }}
1083 public override bool RequireSorting { get { return _requireSorting; } }
1087 internal class ListIterator : BaseIterator
1089 protected IList _list;
1091 bool _requireSorting;
1093 public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter)
1095 if (!(list is ICloneable))
1096 throw new ArgumentException ("Target enumerator must be cloneable.");
1098 _requireSorting = requireSorting;
1101 public ListIterator (IList list, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
1103 if (!(list is ICloneable))
1104 throw new ArgumentException ("Target enumerator must be cloneable.");
1106 _requireSorting = requireSorting;
1109 protected ListIterator (ListIterator other) : base (other)
1111 ICloneable listClone = other._list as ICloneable;
1112 _list = (IList) listClone.Clone ();
1114 _requireSorting = other._requireSorting;
1116 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1118 public override bool MoveNext ()
1120 if (_pos >= _list.Count)
1125 public override XPathNavigator Current {
1127 if (_list.Count == 0)
1129 return (XPathNavigator) _list [_pos - 1];
1132 public override int CurrentPosition { get { return _pos; }}
1134 public override bool RequireSorting { get { return _requireSorting; } }
1136 public override int Count { get { return _list.Count; } }
1140 internal class UnionIterator : BaseIterator
1142 protected BaseIterator _left, _right;
1144 private bool keepLeft;
1145 private bool keepRight;
1146 private bool useRight;
1148 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
1154 protected UnionIterator (UnionIterator other) : base (other)
1156 _left = (BaseIterator) other._left.Clone ();
1157 _right = (BaseIterator) other._right.Clone ();
1159 keepLeft = other.keepLeft;
1160 keepRight = other.keepRight;
1161 useRight = other.useRight;
1163 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1165 public override bool MoveNext ()
1168 keepLeft = _left.MoveNext ();
1170 keepRight = _right.MoveNext ();
1172 if (!keepLeft && !keepRight)
1177 keepLeft = useRight = false;
1179 } else if (!keepLeft) {
1185 switch (_left.Current.ComparePosition (_right.Current)) {
1186 case XmlNodeOrder.Same:
1187 // consume both. i.e. don't output duplicate result.
1188 keepLeft = keepRight = false;
1191 case XmlNodeOrder.Before:
1192 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1193 keepLeft = useRight = false;
1195 case XmlNodeOrder.After:
1200 throw new InvalidOperationException ("Should not happen.");
1203 public override XPathNavigator Current
1210 return _right.Current;
1212 return _left.Current;
1215 public override int CurrentPosition { get { return _pos; }}
1217 public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }