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 XmlNamespaceManager _nsm;
22 internal BaseIterator (BaseIterator other)
26 internal BaseIterator (XmlNamespaceManager nsm)
31 public XmlNamespaceManager NamespaceManager { get { return _nsm; } }
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, XmlNamespaceManager nsm) : base (nsm)
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, XmlNamespaceManager nsm) : base (nav, nsm) {}
114 protected SelfIterator (SimpleIterator other) : base (other) {}
115 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
116 public override bool MoveNext ()
127 internal class NullIterator : SelfIterator
129 public NullIterator (BaseIterator iter) : base (iter) {}
130 public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
131 protected NullIterator (SimpleIterator other) : base (other) {}
132 public override XPathNodeIterator Clone () { return new NullIterator (this); }
133 public override bool MoveNext ()
139 internal class ParentIterator : SimpleIterator
141 public ParentIterator (BaseIterator iter) : base (iter) {}
142 protected ParentIterator (SimpleIterator other) : base (other) {}
143 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
144 public override bool MoveNext ()
146 if (_pos == 0 && _nav.MoveToParent ())
155 internal class ChildIterator : SimpleIterator
157 public ChildIterator (BaseIterator iter) : base (iter) {}
158 protected ChildIterator (SimpleIterator other) : base (other) {}
159 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
160 public override bool MoveNext ()
162 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
169 internal class FollowingSiblingIterator : SimpleIterator
171 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
172 protected FollowingSiblingIterator (SimpleIterator other) : base (other) {}
173 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
174 public override bool MoveNext ()
176 if (_nav.MoveToNext ())
185 internal class PrecedingSiblingIterator : SimpleIterator
187 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
188 protected PrecedingSiblingIterator (SimpleIterator other) : base (other) {}
189 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
190 public override bool MoveNext ()
192 if (_nav.MoveToPrevious ())
201 internal class AncestorIterator : SimpleIterator
203 public AncestorIterator (BaseIterator iter) : base (iter) {}
204 protected AncestorIterator (SimpleIterator other) : base (other) {}
205 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
206 public override bool MoveNext ()
208 if (_nav.MoveToParent ())
217 internal class AncestorOrSelfIterator : MergedIterator
219 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
221 Add (new SelfIterator (iter));
222 Add (new AncestorIterator (iter));
224 protected AncestorOrSelfIterator (MergedIterator other) : base (other) {}
225 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
228 internal class DescendantIterator : SimpleIterator
230 protected int _depth;
231 public DescendantIterator (BaseIterator iter) : base (iter) {}
232 protected DescendantIterator (SimpleIterator other) : base (other) {}
233 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
235 public override bool MoveNext ()
237 if (_nav.MoveToFirstChild ())
245 if (_nav.MoveToNext ())
250 if (!_nav.MoveToParent ()) // should NEVER fail!
251 throw new XPathException ("unexpected depth"); // TODO: better message
258 internal class DescendantOrSelfIterator : MergedIterator
260 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
262 Add (new SelfIterator (iter));
263 Add (new DescendantIterator (iter));
265 protected DescendantOrSelfIterator (MergedIterator other) : base (other) {}
266 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
269 internal class FollowingIterator : SimpleIterator
271 public FollowingIterator (BaseIterator iter) : base (iter) {}
272 protected FollowingIterator (SimpleIterator other) : base (other) {}
273 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
274 public override bool MoveNext ()
278 if (_nav.MoveToNext ())
286 if (_nav.MoveToFirstChild ())
293 if (_nav.MoveToNext ())
299 while (_nav.MoveToParent ());
305 internal class PrecedingIterator : SimpleIterator
307 public PrecedingIterator (BaseIterator iter) : base (iter) {}
308 protected PrecedingIterator (SimpleIterator other) : base (other) {}
309 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
310 public override bool MoveNext ()
314 if (_nav.MoveToPrevious ())
322 if (_nav.MoveToFirstChild ())
324 while (_nav.MoveToNext ())
331 if (_nav.MoveToPrevious ())
337 while (_nav.MoveToParent ());
343 internal class NamespaceIterator : SimpleIterator
345 public NamespaceIterator (BaseIterator iter) : base (iter) {}
346 protected NamespaceIterator (SimpleIterator other) : base (other) {}
347 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
348 public override bool MoveNext ()
352 if (_nav.MoveToFirstNamespace ())
358 else if (_nav.MoveToNextNamespace ())
367 internal class AttributeIterator : SimpleIterator
369 public AttributeIterator (BaseIterator iter) : base (iter) {}
370 protected AttributeIterator (SimpleIterator other) : base (other) {}
371 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
372 public override bool MoveNext ()
376 if (_nav.MoveToFirstAttribute ())
382 else if (_nav.MoveToNextAttribute ())
391 internal class AxisIterator : BaseIterator
393 protected BaseIterator _iter;
394 protected NodeTest _test;
397 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
403 protected AxisIterator (AxisIterator other) : base (other)
405 _iter = (BaseIterator) other._iter.Clone ();
409 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
411 public override bool MoveNext ()
413 while (_iter.MoveNext ())
415 if (_test.Match (NamespaceManager, Current))
423 public override XPathNavigator Current { get { return _iter.Current; }}
424 public override int CurrentPosition { get { return _pos; }}
427 internal class SlashIterator : BaseIterator
429 protected BaseIterator _iterLeft;
430 protected BaseIterator _iterRight;
431 protected Expression _expr;
434 public SlashIterator (BaseIterator iter, Expression expr) : base (iter)
440 protected SlashIterator (SlashIterator other) : base (other)
442 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
443 if (other._iterRight != null)
444 _iterRight = (BaseIterator) other._iterRight.Clone ();
448 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
450 public override bool MoveNext ()
452 while (_iterRight == null || !_iterRight.MoveNext ())
454 if (!_iterLeft.MoveNext ())
456 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
461 public override XPathNavigator Current { get { return _iterRight.Current; }}
462 public override int CurrentPosition { get { return _pos; }}
464 internal class PredicateIterator : BaseIterator
466 protected BaseIterator _iter;
467 protected Expression [] _preds;
470 public PredicateIterator (BaseIterator iter, Expression [] preds) : base (iter)
476 protected PredicateIterator (PredicateIterator other) : base (other)
478 _iter = (BaseIterator) other._iter.Clone ();
479 _preds = other._preds;
482 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
484 public override bool MoveNext ()
486 while (_iter.MoveNext ())
489 foreach (Expression pred in _preds)
491 object result = pred.Evaluate ((BaseIterator) _iter.Clone ());
492 if (result is double)
494 if ((double) result != _iter.CurrentPosition)
500 else if (!XPathFunctions.ToBoolean (result))
511 public override XPathNavigator Current { get { return _iter.Current; }}
512 public override int CurrentPosition { get { return _pos; }}
514 internal class ArrayListIterator : BaseIterator
516 protected ArrayList _rgNodes;
519 public ArrayListIterator (BaseIterator iter, ArrayList rgNodes) : base (iter)
524 protected ArrayListIterator (ArrayListIterator other) : base (other)
526 _rgNodes = other._rgNodes;
529 public override XPathNodeIterator Clone () { return new ArrayListIterator (this); }
531 public override bool MoveNext ()
533 if (_pos >= _rgNodes.Count)
538 public override XPathNavigator Current { get { return (XPathNavigator) _rgNodes [_pos - 1]; }}
539 public override int CurrentPosition { get { return _pos; }}
542 internal class UnionIterator : BaseIterator
544 protected ArrayList _rgNodes;
545 protected BaseIterator _left, _right;
548 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
550 _rgNodes = new ArrayList ();
555 protected UnionIterator (UnionIterator other) : base (other)
557 _rgNodes = (ArrayList) other._rgNodes.Clone ();
559 _right = other._right;
562 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
564 public override bool MoveNext ()
566 if (_left.MoveNext ())
568 _rgNodes.Add (_left.Current.Clone ());
573 while (_right.MoveNext ())
575 XPathNavigator navRight = _right.Current;
577 foreach (XPathNavigator navLeft in _rgNodes)
579 if (navLeft.IsSamePosition (navRight))
593 public override XPathNavigator Current
597 if (_pos < _rgNodes.Count)
598 throw new XPathException ("bug in UnionOperator"); // TODO: better exception
599 if (_pos == _rgNodes.Count)
600 return _left.Current;
602 return _right.Current;
605 public override int CurrentPosition { get { return _pos; }}