2 // System.Xml.XPath.BaseIterator
5 // Piers Haken (piersh@friskit.com)
7 // (C) 2002 Piers Haken
11 using System.Collections;
13 using System.Xml.XPath;
16 namespace System.Xml.XPath
18 internal abstract class BaseIterator : XPathNodeIterator
20 private XsltContext _context;
22 internal BaseIterator (BaseIterator other)
24 _context = other._context;
26 internal BaseIterator (XsltContext context)
31 public XsltContext Context { get { return _context; } }
33 public override string ToString ()
35 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
39 internal class MergedIterator : BaseIterator
41 protected ArrayList _iters = new ArrayList ();
45 public MergedIterator (BaseIterator iter ) : base (iter) {}
46 protected MergedIterator (MergedIterator other) : base (other)
48 foreach (object obj in other._iters)
51 _index = other._index;
53 public override XPathNodeIterator Clone () { return new MergedIterator (this); }
55 public void Add (BaseIterator iter)
60 public override bool MoveNext ()
62 while (_index < _iters.Count)
64 BaseIterator iter = (BaseIterator) _iters [_index];
74 public override XPathNavigator Current
78 if (_index >= _iters.Count)
80 BaseIterator iter = (BaseIterator) _iters [_index];
84 public override int CurrentPosition { get { return _pos; }}
87 internal abstract class SimpleIterator : BaseIterator
89 protected XPathNavigator _nav;
92 public SimpleIterator (BaseIterator iter) : base (iter)
94 _nav = iter.Current.Clone ();
96 protected SimpleIterator (SimpleIterator other) : base (other)
98 _nav = other._nav.Clone ();
101 public SimpleIterator (XPathNavigator nav, XsltContext context) : base (context)
106 public override XPathNavigator Current { get { return _nav; }}
107 public override int CurrentPosition { get { return _pos; }}
110 internal class SelfIterator : SimpleIterator
112 public SelfIterator (BaseIterator iter) : base (iter) {}
113 public SelfIterator (XPathNavigator nav, XsltContext context) : base (nav, context) {}
114 protected SelfIterator (SimpleIterator other) : base (other) {}
115 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
116 public override bool MoveNext ()
127 internal class ParentIterator : SimpleIterator
129 public ParentIterator (BaseIterator iter) : base (iter) {}
130 protected ParentIterator (SimpleIterator other) : base (other) {}
131 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
132 public override bool MoveNext ()
134 if (_pos == 0 && _nav.MoveToParent ())
143 internal class ChildIterator : SimpleIterator
145 public ChildIterator (BaseIterator iter) : base (iter) {}
146 protected ChildIterator (SimpleIterator other) : base (other) {}
147 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
148 public override bool MoveNext ()
150 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
157 internal class FollowingSiblingIterator : SimpleIterator
159 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
160 protected FollowingSiblingIterator (SimpleIterator other) : base (other) {}
161 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
162 public override bool MoveNext ()
164 if (_nav.MoveToNext ())
173 internal class PrecedingSiblingIterator : SimpleIterator
175 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
176 protected PrecedingSiblingIterator (SimpleIterator other) : base (other) {}
177 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
178 public override bool MoveNext ()
180 if (_nav.MoveToPrevious ())
189 internal class AncestorIterator : SimpleIterator
191 public AncestorIterator (BaseIterator iter) : base (iter) {}
192 protected AncestorIterator (SimpleIterator other) : base (other) {}
193 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
194 public override bool MoveNext ()
196 if (_nav.MoveToParent ())
205 internal class AncestorOrSelfIterator : MergedIterator
207 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
209 Add (new SelfIterator (iter));
210 Add (new AncestorIterator (iter));
212 protected AncestorOrSelfIterator (MergedIterator other) : base (other) {}
213 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
216 internal class DescendantIterator : SimpleIterator
218 protected int _depth;
219 public DescendantIterator (BaseIterator iter) : base (iter) {}
220 protected DescendantIterator (SimpleIterator other) : base (other) {}
221 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
223 public override bool MoveNext ()
225 if (_nav.MoveToFirstChild ())
233 if (_nav.MoveToNext ())
238 if (!_nav.MoveToParent ()) // should NEVER fail!
239 throw new Exception ("unexpected depth"); // TODO: better message
246 internal class DescendantOrSelfIterator : MergedIterator
248 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
250 Add (new SelfIterator (iter));
251 Add (new DescendantIterator (iter));
253 protected DescendantOrSelfIterator (MergedIterator other) : base (other) {}
254 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
257 internal class FollowingIterator : SimpleIterator
259 public FollowingIterator (BaseIterator iter) : base (iter) {}
260 protected FollowingIterator (SimpleIterator other) : base (other) {}
261 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
262 public override bool MoveNext ()
266 if (_nav.MoveToNext ())
274 if (_nav.MoveToFirstChild ())
281 if (_nav.MoveToNext ())
287 while (_nav.MoveToParent ());
293 internal class PrecedingIterator : SimpleIterator
295 public PrecedingIterator (BaseIterator iter) : base (iter) {}
296 protected PrecedingIterator (SimpleIterator other) : base (other) {}
297 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
298 public override bool MoveNext ()
302 if (_nav.MoveToPrevious ())
310 if (_nav.MoveToFirstChild ())
312 while (_nav.MoveToNext ())
319 if (_nav.MoveToPrevious ())
325 while (_nav.MoveToParent ());
331 internal class NamespaceIterator : SimpleIterator
333 public NamespaceIterator (BaseIterator iter) : base (iter) {}
334 protected NamespaceIterator (SimpleIterator other) : base (other) {}
335 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
336 public override bool MoveNext ()
340 if (_nav.MoveToFirstNamespace ())
346 else if (_nav.MoveToNextNamespace ())
355 internal class AttributeIterator : SimpleIterator
357 public AttributeIterator (BaseIterator iter) : base (iter) {}
358 protected AttributeIterator (SimpleIterator other) : base (other) {}
359 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
360 public override bool MoveNext ()
364 if (_nav.MoveToFirstAttribute ())
370 else if (_nav.MoveToNextAttribute ())
379 internal class AxisIterator : BaseIterator
381 protected BaseIterator _iter;
382 protected NodeTest _test;
385 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
391 protected AxisIterator (AxisIterator other) : base (other)
393 _iter = (BaseIterator) other._iter.Clone ();
397 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
399 public override bool MoveNext ()
401 while (_iter.MoveNext ())
403 if (_test.Match (Context, Current))
411 public override XPathNavigator Current { get { return _iter.Current; }}
412 public override int CurrentPosition { get { return _pos; }}
415 internal class SlashIterator : BaseIterator
417 protected BaseIterator _iterLeft;
418 protected BaseIterator _iterRight;
419 protected Expression _expr;
422 public SlashIterator (BaseIterator iter, Expression expr) : base (iter)
428 protected SlashIterator (SlashIterator other) : base (other)
430 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
431 _iterRight = (BaseIterator) other._iterRight.Clone ();
435 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
437 public override bool MoveNext ()
439 while (_iterRight == null || !_iterRight.MoveNext ())
441 if (!_iterLeft.MoveNext ())
443 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
448 public override XPathNavigator Current { get { return _iterRight.Current; }}
449 public override int CurrentPosition { get { return _pos; }}
451 internal class PredicateIterator : BaseIterator
453 protected BaseIterator _iter;
454 protected Expression [] _preds;
457 public PredicateIterator (BaseIterator iter, Expression [] preds) : base (iter)
463 protected PredicateIterator (PredicateIterator other) : base (other)
465 _iter = (BaseIterator) other._iter.Clone ();
466 _preds = other._preds;
469 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
471 public override bool MoveNext ()
473 while (_iter.MoveNext ())
476 foreach (Expression pred in _preds)
478 object result = pred.Evaluate ((BaseIterator) _iter.Clone ());
479 if (result is double)
481 if ((double) result != _iter.CurrentPosition)
487 else if (!XPathFunctions.ToBoolean (result))
498 public override XPathNavigator Current { get { return _iter.Current; }}
499 public override int CurrentPosition { get { return _pos; }}
501 internal class ArrayListIterator : BaseIterator
503 protected ArrayList _rgNodes;
506 public ArrayListIterator (BaseIterator iter, ArrayList rgNodes) : base (iter)
511 protected ArrayListIterator (ArrayListIterator other) : base (other)
513 _rgNodes = other._rgNodes;
516 public override XPathNodeIterator Clone () { return new ArrayListIterator (this); }
518 public override bool MoveNext ()
520 if (_pos >= _rgNodes.Count)
525 public override XPathNavigator Current { get { return (XPathNavigator) _rgNodes [_pos - 1]; }}
526 public override int CurrentPosition { get { return _pos; }}
529 internal class UnionIterator : BaseIterator
531 protected ArrayList _rgNodes;
532 protected BaseIterator _left, _right;
535 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
537 _rgNodes = new ArrayList ();
542 protected UnionIterator (UnionIterator other) : base (other)
544 _rgNodes = (ArrayList) other._rgNodes.Clone ();
546 _right = other._right;
549 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
551 public override bool MoveNext ()
553 if (_left.MoveNext ())
555 _rgNodes.Add (_left.Current.Clone ());
560 while (_right.MoveNext ())
562 XPathNavigator navRight = _right.Current;
564 foreach (XPathNavigator navLeft in _rgNodes)
566 if (navLeft.IsSamePosition (navRight))
580 public override XPathNavigator Current
584 if (_pos < _rgNodes.Count)
585 throw new Exception ("bug in UnionOperator"); // TODO: better exception
586 if (_pos == _rgNodes.Count)
587 return _left.Current;
589 return _right.Current;
592 public override int CurrentPosition { get { return _pos; }}