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
19 internal abstract class XPathNodeIterator : ICloneable
25 protected XPathNodeIterator () {}
31 public virtual int Count
37 // compute and cache the count
38 XPathNodeIterator tmp = Clone ();
39 while (tmp.MoveNext ())
41 _count = tmp.CurrentPosition;
47 public abstract XPathNavigator Current { get; }
49 public abstract int CurrentPosition { get; }
55 public abstract XPathNodeIterator Clone ();
57 object ICloneable.Clone ()
62 public abstract bool MoveNext ();
68 internal abstract class BaseIterator : XPathNodeIterator
70 private XsltContext _context;
72 internal BaseIterator (BaseIterator other)
74 _context = other._context;
76 internal BaseIterator (XsltContext context)
81 public XsltContext Context { get { return _context; } }
83 public override string ToString ()
85 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
89 internal class UnionIterator : BaseIterator
91 protected ArrayList _iters = new ArrayList ();
95 public UnionIterator (BaseIterator iter ) : base (iter) {}
96 protected UnionIterator (UnionIterator other) : base (other)
98 foreach (object obj in other._iters)
101 _index = other._index;
103 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
105 public void Add (BaseIterator iter)
110 public override bool MoveNext ()
112 while (_index < _iters.Count)
114 BaseIterator iter = (BaseIterator) _iters [_index];
115 if (iter.MoveNext ())
124 public override XPathNavigator Current
128 if (_index >= _iters.Count)
130 BaseIterator iter = (BaseIterator) _iters [_index];
134 public override int CurrentPosition { get { return _pos; }}
137 internal abstract class SimpleIterator : BaseIterator
139 protected XPathNavigator _nav;
142 public SimpleIterator (BaseIterator iter) : base (iter)
144 _nav = iter.Current.Clone ();
146 protected SimpleIterator (SimpleIterator other) : base (other)
148 _nav = other._nav.Clone ();
151 public SimpleIterator (XPathNavigator nav, XsltContext context) : base (context)
156 public override XPathNavigator Current { get { return _nav; }}
157 public override int CurrentPosition { get { return _pos; }}
160 internal class SelfIterator : SimpleIterator
162 public SelfIterator (BaseIterator iter) : base (iter) {}
163 public SelfIterator (XPathNavigator nav, XsltContext context) : base (nav, context) {}
164 protected SelfIterator (SimpleIterator other) : base (other) {}
165 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
166 public override bool MoveNext ()
177 internal class ParentIterator : SimpleIterator
179 public ParentIterator (BaseIterator iter) : base (iter) {}
180 protected ParentIterator (SimpleIterator other) : base (other) {}
181 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
182 public override bool MoveNext ()
184 if (_pos == 0 && _nav.MoveToParent ())
193 internal class ChildIterator : SimpleIterator
195 public ChildIterator (BaseIterator iter) : base (iter) {}
196 protected ChildIterator (SimpleIterator other) : base (other) {}
197 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
198 public override bool MoveNext ()
200 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
207 internal class FollowingSiblingIterator : SimpleIterator
209 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
210 protected FollowingSiblingIterator (SimpleIterator other) : base (other) {}
211 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
212 public override bool MoveNext ()
214 if (_nav.MoveToNext ())
223 internal class PrecedingSiblingIterator : SimpleIterator
225 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
226 protected PrecedingSiblingIterator (SimpleIterator other) : base (other) {}
227 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
228 public override bool MoveNext ()
230 if (_nav.MoveToPrevious ())
239 internal class AncestorIterator : SimpleIterator
241 public AncestorIterator (BaseIterator iter) : base (iter) {}
242 protected AncestorIterator (SimpleIterator other) : base (other) {}
243 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
244 public override bool MoveNext ()
246 if (_nav.MoveToParent ())
255 internal class AncestorOrSelfIterator : UnionIterator
257 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
259 Add (new SelfIterator (iter));
260 Add (new AncestorIterator (iter));
262 protected AncestorOrSelfIterator (UnionIterator other) : base (other) {}
263 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
266 internal class DescendantIterator : SimpleIterator
268 protected int _depth;
269 public DescendantIterator (BaseIterator iter) : base (iter) {}
270 protected DescendantIterator (SimpleIterator other) : base (other) {}
271 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
273 public override bool MoveNext ()
275 if (_nav.MoveToFirstChild ())
283 if (_nav.MoveToNext ())
288 if (!_nav.MoveToParent ()) // should NEVER fail!
289 throw new Exception ("unexpected depth"); // TODO: better message
296 internal class DescendantOrSelfIterator : UnionIterator
298 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
300 Add (new SelfIterator (iter));
301 Add (new DescendantIterator (iter));
303 protected DescendantOrSelfIterator (UnionIterator other) : base (other) {}
304 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
307 internal class FollowingIterator : SimpleIterator
309 public FollowingIterator (BaseIterator iter) : base (iter) {}
310 protected FollowingIterator (SimpleIterator other) : base (other) {}
311 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
312 public override bool MoveNext ()
316 if (_nav.MoveToNext ())
324 if (_nav.MoveToFirstChild ())
331 if (_nav.MoveToNext ())
337 while (_nav.MoveToParent ());
343 internal class PrecedingIterator : SimpleIterator
345 public PrecedingIterator (BaseIterator iter) : base (iter) {}
346 protected PrecedingIterator (SimpleIterator other) : base (other) {}
347 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
348 public override bool MoveNext ()
352 if (_nav.MoveToPrevious ())
360 if (_nav.MoveToFirstChild ())
362 while (_nav.MoveToNext ())
369 if (_nav.MoveToPrevious ())
375 while (_nav.MoveToParent ());
381 internal class NamespaceIterator : SimpleIterator
383 public NamespaceIterator (BaseIterator iter) : base (iter) {}
384 protected NamespaceIterator (SimpleIterator other) : base (other) {}
385 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
386 public override bool MoveNext ()
390 if (_nav.MoveToFirstNamespace ())
396 else if (_nav.MoveToNextNamespace ())
405 internal class AttributeIterator : SimpleIterator
407 public AttributeIterator (BaseIterator iter) : base (iter) {}
408 protected AttributeIterator (SimpleIterator other) : base (other) {}
409 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
410 public override bool MoveNext ()
414 if (_nav.MoveToFirstAttribute ())
420 else if (_nav.MoveToNextAttribute ())
429 internal class AxisIterator : BaseIterator
431 protected BaseIterator _iter;
432 protected NodeTest _test;
435 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
441 protected AxisIterator (AxisIterator other) : base (other)
443 _iter = (BaseIterator) other._iter.Clone ();
447 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
449 public override bool MoveNext ()
451 while (_iter.MoveNext ())
453 if (_test.Match (Context, Current))
461 public override XPathNavigator Current { get { return _iter.Current; }}
462 public override int CurrentPosition { get { return _pos; }}
465 internal class SlashIterator : BaseIterator
467 protected BaseIterator _iterLeft;
468 protected BaseIterator _iterRight;
469 protected Expression _expr;
472 public SlashIterator (BaseIterator iter, Expression expr) : base (iter)
478 protected SlashIterator (SlashIterator other) : base (other)
480 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
481 _iterRight = (BaseIterator) other._iterRight.Clone ();
485 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
487 public override bool MoveNext ()
489 while (_iterRight == null || !_iterRight.MoveNext ())
491 if (!_iterLeft.MoveNext ())
493 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
498 public override XPathNavigator Current { get { return _iterRight.Current; }}
499 public override int CurrentPosition { get { return _pos; }}
501 internal class PredicateIterator : BaseIterator
503 protected BaseIterator _iter;
504 protected Expression [] _preds;
507 public PredicateIterator (BaseIterator iter, Expression [] preds) : base (iter)
513 protected PredicateIterator (PredicateIterator other) : base (other)
515 _iter = (BaseIterator) other._iter.Clone ();
516 _preds = other._preds;
519 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
521 public override bool MoveNext ()
523 while (_iter.MoveNext ())
526 foreach (Expression pred in _preds)
528 object result = pred.Evaluate ((BaseIterator) _iter.Clone ());
529 if (result is double)
531 if ((double) result != _iter.CurrentPosition)
537 else if (!XPathFunctions.ToBoolean (result))
548 public override XPathNavigator Current { get { return _iter.Current; }}
549 public override int CurrentPosition { get { return _pos; }}
551 internal class ArrayListIterator : BaseIterator
553 protected ArrayList _rgNodes;
556 public ArrayListIterator (BaseIterator iter, ArrayList rgNodes) : base (iter)
561 protected ArrayListIterator (ArrayListIterator other) : base (other)
563 _rgNodes = other._rgNodes;
565 public override XPathNodeIterator Clone () { return new ArrayListIterator (this); }
567 public override bool MoveNext ()
569 if (_pos >= _rgNodes.Count)
574 public override XPathNavigator Current { get { return (XPathNavigator) _rgNodes [_pos - 1]; }}
575 public override int CurrentPosition { get { return _pos; }}