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
37 public override string ToString ()
40 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
42 return this.GetType().ToString () + "[" + CurrentPosition + "]";
46 internal class MergedIterator : BaseIterator
48 protected ArrayList _iters = new ArrayList ();
52 public MergedIterator (BaseIterator iter ) : base (iter) {}
53 protected MergedIterator (MergedIterator other) : base (other)
55 foreach (XPathNodeIterator iter in other._iters)
56 _iters.Add (iter.Clone ());
58 _index = other._index;
60 public override XPathNodeIterator Clone () { return new MergedIterator (this); }
62 public void Add (BaseIterator iter)
67 public override bool MoveNext ()
69 while (_index < _iters.Count)
71 BaseIterator iter = (BaseIterator) _iters [_index];
81 public override XPathNavigator Current
85 if (_index >= _iters.Count)
87 BaseIterator iter = (BaseIterator) _iters [_index];
91 public override int CurrentPosition { get { return _pos; }}
94 internal abstract class SimpleIterator : BaseIterator
96 protected XPathNavigator _nav;
99 public SimpleIterator (BaseIterator iter) : base (iter)
101 _nav = iter.Current.Clone ();
103 protected SimpleIterator (SimpleIterator other) : base (other)
105 _nav = other._nav.Clone ();
108 public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
113 public override XPathNavigator Current { get { return _nav; }}
114 public override int CurrentPosition { get { return _pos; }}
117 internal class SelfIterator : SimpleIterator
119 public SelfIterator (BaseIterator iter) : base (iter) {}
120 public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
121 protected SelfIterator (SelfIterator other) : base (other) {}
122 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
123 public override bool MoveNext ()
134 internal class NullIterator : SelfIterator
136 public NullIterator (BaseIterator iter) : base (iter) {}
137 public NullIterator (XPathNavigator nav) : this (nav, null) {}
138 public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
139 protected NullIterator (NullIterator other) : base (other) {}
140 public override XPathNodeIterator Clone () { return new NullIterator (this); }
141 public override bool MoveNext ()
147 internal class ParentIterator : SimpleIterator
149 public ParentIterator (BaseIterator iter) : base (iter) {}
150 protected ParentIterator (ParentIterator other) : base (other) {}
151 public ParentIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
152 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
153 public override bool MoveNext ()
155 if (_pos == 0 && _nav.MoveToParent ())
164 internal class ChildIterator : SimpleIterator
166 public ChildIterator (BaseIterator iter) : base (iter) {}
167 protected ChildIterator (ChildIterator other) : base (other) {}
168 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
169 public override bool MoveNext ()
171 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
178 internal class FollowingSiblingIterator : SimpleIterator
180 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
181 protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
182 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
183 public override bool MoveNext ()
185 if (_nav.MoveToNext ())
194 internal class PrecedingSiblingIterator : SimpleIterator
196 public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
197 protected PrecedingSiblingIterator (PrecedingIterator other) : base (other) {}
198 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
199 public override bool MoveNext ()
201 if (_nav.MoveToPrevious ())
210 internal class AncestorIterator : SimpleIterator
212 public AncestorIterator (BaseIterator iter) : base (iter) {}
213 protected AncestorIterator (AncestorIterator other) : base (other) {}
214 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
215 public override bool MoveNext ()
217 if (_nav.MoveToParent ())
226 internal class AncestorOrSelfIterator : MergedIterator
228 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
230 Add (new SelfIterator (iter));
231 Add (new AncestorIterator (iter));
233 protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other) {}
234 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
237 internal class DescendantIterator : SimpleIterator
239 protected int _depth;
240 public DescendantIterator (BaseIterator iter) : base (iter) {}
241 protected DescendantIterator (DescendantIterator other) : base (other)
243 _depth = other._depth;
245 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
247 public override bool MoveNext ()
249 if (_nav.MoveToFirstChild ())
257 if (_nav.MoveToNext ())
262 if (!_nav.MoveToParent ()) // should NEVER fail!
263 throw new XPathException ("unexpected depth"); // TODO: better message
270 internal class DescendantOrSelfIterator : MergedIterator
272 public DescendantOrSelfIterator (BaseIterator iter) : base (iter)
274 Add (new SelfIterator (iter));
275 Add (new DescendantIterator (iter));
277 protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other) {}
278 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
281 internal class FollowingIterator : SimpleIterator
283 public FollowingIterator (BaseIterator iter) : base (iter) {}
284 protected FollowingIterator (FollowingIterator other) : base (other) {}
285 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
286 public override bool MoveNext ()
290 if (_nav.MoveToNext ())
298 if (_nav.MoveToFirstChild ())
305 if (_nav.MoveToNext ())
311 while (_nav.MoveToParent ());
317 internal class PrecedingIterator : SimpleIterator
319 public PrecedingIterator (BaseIterator iter) : base (iter) {}
320 protected PrecedingIterator (PrecedingIterator other) : base (other) {}
321 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
322 public override bool MoveNext ()
326 if (_nav.MoveToPrevious ())
334 if (_nav.MoveToFirstChild ())
336 while (_nav.MoveToNext ())
343 if (_nav.MoveToPrevious ())
349 while (_nav.MoveToParent ());
355 internal class NamespaceIterator : SimpleIterator
357 public NamespaceIterator (BaseIterator iter) : base (iter) {}
358 protected NamespaceIterator (NamespaceIterator other) : base (other) {}
359 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
360 public override bool MoveNext ()
364 if (_nav.MoveToFirstNamespace ())
370 else if (_nav.MoveToNextNamespace ())
379 internal class AttributeIterator : SimpleIterator
381 public AttributeIterator (BaseIterator iter) : base (iter) {}
382 protected AttributeIterator (AttributeIterator other) : base (other) {}
383 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
384 public override bool MoveNext ()
388 if (_nav.MoveToFirstAttribute ())
394 else if (_nav.MoveToNextAttribute ())
403 internal class AxisIterator : BaseIterator
405 protected BaseIterator _iter;
406 protected NodeTest _test;
409 public AxisIterator (BaseIterator iter, NodeTest test) : base (iter)
415 protected AxisIterator (AxisIterator other) : base (other)
417 _iter = (BaseIterator) other._iter.Clone ();
421 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
423 public override bool MoveNext ()
425 while (_iter.MoveNext ())
427 if (_test.Match (NamespaceManager, Current))
435 public override XPathNavigator Current { get { return _iter.Current; }}
436 public override int CurrentPosition { get { return _pos; }}
439 internal class SlashIterator : BaseIterator
441 protected BaseIterator _iterLeft;
442 protected BaseIterator _iterRight;
443 protected NodeSet _expr;
446 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
452 protected SlashIterator (SlashIterator other) : base (other)
454 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
455 if (other._iterRight != null)
456 _iterRight = (BaseIterator) other._iterRight.Clone ();
460 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
462 public override bool MoveNext ()
464 while (_iterRight == null || !_iterRight.MoveNext ())
466 if (!_iterLeft.MoveNext ())
468 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
473 public override XPathNavigator Current {
475 if (_iterRight == null) return null;
477 return _iterRight.Current;
480 public override int CurrentPosition { get { return _pos; }}
483 internal class PredicateIterator : BaseIterator
485 protected BaseIterator _iter;
486 protected Expression _pred;
489 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
495 protected PredicateIterator (PredicateIterator other) : base (other)
497 _iter = (BaseIterator) other._iter.Clone ();
501 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
503 public override bool MoveNext ()
505 while (_iter.MoveNext ())
508 object result = _pred.Evaluate ((BaseIterator) _iter.Clone ());
509 if (result is double)
511 if ((double) result != _iter.CurrentPosition)
514 else if (!XPathFunctions.ToBoolean (result))
522 public override XPathNavigator Current { get { return _iter.Current; }}
523 public override int CurrentPosition { get { return _pos; }}
526 internal class EnumeratorIterator : BaseIterator
528 protected IEnumerator _enum;
531 public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator) : base (iter)
536 public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm) : base (nsm)
541 protected EnumeratorIterator (EnumeratorIterator other) : base (other)
546 public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
548 public override bool MoveNext ()
550 if (!_enum.MoveNext ())
555 public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
556 public override int CurrentPosition { get { return _pos; }}
560 internal class UnionIterator : BaseIterator
562 protected ArrayList _rgNodes;
563 protected BaseIterator _left, _right;
566 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
568 _rgNodes = new ArrayList ();
573 protected UnionIterator (UnionIterator other) : base (other)
575 _rgNodes = (ArrayList) other._rgNodes.Clone ();
577 _right = other._right;
580 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
582 public override bool MoveNext ()
584 if (_left.MoveNext ())
586 _rgNodes.Add (_left.Current.Clone ());
591 while (_right.MoveNext ())
593 XPathNavigator navRight = _right.Current;
595 foreach (XPathNavigator navLeft in _rgNodes)
597 if (navLeft.IsSamePosition (navRight))
611 public override XPathNavigator Current
615 if (_pos < _rgNodes.Count)
616 throw new XPathException ("bug in UnionOperator"); // TODO: better exception
617 if (_pos == _rgNodes.Count)
618 return _left.Current;
620 return _right.Current;
623 public override int CurrentPosition { get { return _pos; }}