Iterator.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. //
  2. // System.Xml.XPath.BaseIterator
  3. //
  4. // Author:
  5. // Piers Haken ([email protected])
  6. //
  7. // (C) 2002 Piers Haken
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Xml;
  12. using System.Xml.XPath;
  13. using System.Xml.Xsl;
  14. namespace System.Xml.XPath
  15. {
  16. internal abstract class BaseIterator : XPathNodeIterator
  17. {
  18. private XmlNamespaceManager _nsm;
  19. internal BaseIterator (BaseIterator other)
  20. {
  21. _nsm = other._nsm;
  22. }
  23. internal BaseIterator (XmlNamespaceManager nsm)
  24. {
  25. _nsm = nsm;
  26. }
  27. public XmlNamespaceManager NamespaceManager
  28. {
  29. get { return _nsm; }
  30. set { _nsm = value; }
  31. }
  32. public override string ToString ()
  33. {
  34. if (Current != null)
  35. return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
  36. else
  37. return this.GetType().ToString () + "[" + CurrentPosition + "]";
  38. }
  39. }
  40. internal class MergedIterator : BaseIterator
  41. {
  42. protected ArrayList _iters = new ArrayList ();
  43. protected int _pos;
  44. protected int _index;
  45. public MergedIterator (BaseIterator iter ) : base (iter) {}
  46. protected MergedIterator (MergedIterator other) : base (other)
  47. {
  48. foreach (XPathNodeIterator iter in other._iters)
  49. _iters.Add (iter.Clone ());
  50. _pos = other._pos;
  51. _index = other._index;
  52. }
  53. public override XPathNodeIterator Clone () { return new MergedIterator (this); }
  54. public void Add (BaseIterator iter)
  55. {
  56. _iters.Add (iter);
  57. }
  58. public override bool MoveNext ()
  59. {
  60. while (_index < _iters.Count)
  61. {
  62. BaseIterator iter = (BaseIterator) _iters [_index];
  63. if (iter.MoveNext ())
  64. {
  65. _pos ++;
  66. return true;
  67. }
  68. _index ++;
  69. }
  70. return false;
  71. }
  72. public override XPathNavigator Current
  73. {
  74. get
  75. {
  76. if (_index >= _iters.Count)
  77. return null;
  78. BaseIterator iter = (BaseIterator) _iters [_index];
  79. return iter.Current;
  80. }
  81. }
  82. public override int CurrentPosition { get { return _pos; }}
  83. }
  84. internal abstract class SimpleIterator : BaseIterator
  85. {
  86. protected readonly XPathNavigator _nav;
  87. protected int _pos;
  88. public SimpleIterator (BaseIterator iter) : base (iter)
  89. {
  90. _nav = iter.Current.Clone ();
  91. }
  92. protected SimpleIterator (SimpleIterator other) : base (other)
  93. {
  94. _nav = other._nav.Clone ();
  95. _pos = other._pos;
  96. }
  97. public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
  98. {
  99. _nav = nav.Clone ();
  100. }
  101. public override XPathNavigator Current { get { return _nav; }}
  102. public override int CurrentPosition { get { return _pos; }}
  103. }
  104. internal class SelfIterator : SimpleIterator
  105. {
  106. public SelfIterator (BaseIterator iter) : base (iter) {}
  107. public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  108. protected SelfIterator (SelfIterator other) : base (other) {}
  109. public override XPathNodeIterator Clone () { return new SelfIterator (this); }
  110. public override bool MoveNext ()
  111. {
  112. if (_pos == 0)
  113. {
  114. _pos = 1;
  115. return true;
  116. }
  117. return false;
  118. }
  119. }
  120. internal class NullIterator : SelfIterator
  121. {
  122. public NullIterator (BaseIterator iter) : base (iter) {}
  123. public NullIterator (XPathNavigator nav) : this (nav, null) {}
  124. public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  125. protected NullIterator (NullIterator other) : base (other) {}
  126. public override XPathNodeIterator Clone () { return new NullIterator (this); }
  127. public override bool MoveNext ()
  128. {
  129. return false;
  130. }
  131. }
  132. internal class ParentIterator : SimpleIterator
  133. {
  134. public ParentIterator (BaseIterator iter) : base (iter) {}
  135. protected ParentIterator (ParentIterator other) : base (other) {}
  136. public ParentIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  137. public override XPathNodeIterator Clone () { return new ParentIterator (this); }
  138. public override bool MoveNext ()
  139. {
  140. if (_pos == 0 && _nav.MoveToParent ())
  141. {
  142. _pos = 1;
  143. return true;
  144. }
  145. return false;
  146. }
  147. }
  148. internal class ChildIterator : SimpleIterator
  149. {
  150. public ChildIterator (BaseIterator iter) : base (iter) {}
  151. protected ChildIterator (ChildIterator other) : base (other) {}
  152. public override XPathNodeIterator Clone () { return new ChildIterator (this); }
  153. public override bool MoveNext ()
  154. {
  155. bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
  156. if (fSuccess)
  157. _pos ++;
  158. return fSuccess;
  159. }
  160. }
  161. internal class FollowingSiblingIterator : SimpleIterator
  162. {
  163. public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
  164. protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
  165. public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
  166. public override bool MoveNext ()
  167. {
  168. if (_nav.MoveToNext ())
  169. {
  170. _pos ++;
  171. return true;
  172. }
  173. return false;
  174. }
  175. }
  176. internal class PrecedingSiblingIterator : SimpleIterator
  177. {
  178. public PrecedingSiblingIterator (BaseIterator iter) : base (iter) {}
  179. protected PrecedingSiblingIterator (PrecedingIterator other) : base (other) {}
  180. public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
  181. public override bool MoveNext ()
  182. {
  183. if (_nav.MoveToPrevious ())
  184. {
  185. _pos ++;
  186. return true;
  187. }
  188. return false;
  189. }
  190. }
  191. internal class AncestorIterator : SimpleIterator
  192. {
  193. public AncestorIterator (BaseIterator iter) : base (iter) {}
  194. protected AncestorIterator (AncestorIterator other) : base (other) {}
  195. public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
  196. public override bool MoveNext ()
  197. {
  198. if (_nav.MoveToParent ())
  199. {
  200. _pos ++;
  201. return true;
  202. }
  203. return false;
  204. }
  205. }
  206. internal class AncestorOrSelfIterator : SimpleIterator
  207. {
  208. public AncestorOrSelfIterator (BaseIterator iter) : base (iter) {}
  209. protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other) {}
  210. public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
  211. public override bool MoveNext ()
  212. {
  213. if (_pos == 0)
  214. {
  215. _pos ++;
  216. return true;
  217. }
  218. if (_nav.MoveToParent ())
  219. {
  220. _pos ++;
  221. return true;
  222. }
  223. return false;
  224. }
  225. }
  226. internal class DescendantIterator : SimpleIterator
  227. {
  228. protected int _depth;
  229. private bool _finished;
  230. public DescendantIterator (BaseIterator iter) : base (iter) {}
  231. protected DescendantIterator (DescendantIterator other) : base (other)
  232. {
  233. _depth = other._depth;
  234. }
  235. public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
  236. [MonoTODO]
  237. public override bool MoveNext ()
  238. {
  239. if (_finished)
  240. return false;
  241. if (_nav.MoveToFirstChild ())
  242. {
  243. _depth ++;
  244. _pos ++;
  245. return true;
  246. }
  247. while (_depth != 0)
  248. {
  249. if (_nav.MoveToNext ())
  250. {
  251. _pos ++;
  252. return true;
  253. }
  254. if (!_nav.MoveToParent ()) // should NEVER fail!
  255. throw new XPathException ("unexpected depth"); // TODO: better message
  256. _depth --;
  257. }
  258. _finished = true;
  259. return false;
  260. }
  261. }
  262. internal class DescendantOrSelfIterator : SimpleIterator
  263. {
  264. protected int _depth;
  265. private bool _finished;
  266. public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
  267. protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
  268. {
  269. _depth = other._depth;
  270. }
  271. public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
  272. [MonoTODO]
  273. public override bool MoveNext ()
  274. {
  275. if (_finished)
  276. return false;
  277. if (_pos == 0)
  278. {
  279. // self
  280. _pos ++;
  281. return true;
  282. }
  283. if (_nav.MoveToFirstChild ())
  284. {
  285. _depth ++;
  286. _pos ++;
  287. return true;
  288. }
  289. while (_depth != 0)
  290. {
  291. if (_nav.MoveToNext ())
  292. {
  293. _pos ++;
  294. return true;
  295. }
  296. if (!_nav.MoveToParent ()) // should NEVER fail!
  297. throw new XPathException ("unexpected depth"); // TODO: better message
  298. _depth --;
  299. }
  300. _finished = true;
  301. return false;
  302. }
  303. }
  304. internal class FollowingIterator : SimpleIterator
  305. {
  306. private bool _finished = false;
  307. public FollowingIterator (BaseIterator iter) : base (iter) {}
  308. protected FollowingIterator (FollowingIterator other) : base (other) {}
  309. public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
  310. public override bool MoveNext ()
  311. {
  312. if (_finished)
  313. return false;
  314. if (_pos == 0)
  315. {
  316. if (_nav.MoveToNext ())
  317. {
  318. _pos ++;
  319. return true;
  320. }
  321. }
  322. else
  323. {
  324. if (_nav.MoveToFirstChild ())
  325. {
  326. _pos ++;
  327. return true;
  328. }
  329. do
  330. {
  331. if (_nav.MoveToNext ())
  332. {
  333. _pos ++;
  334. return true;
  335. }
  336. }
  337. while (_nav.MoveToParent ());
  338. }
  339. _finished = true;
  340. return false;
  341. }
  342. }
  343. internal class PrecedingIterator : SimpleIterator
  344. {
  345. public PrecedingIterator (BaseIterator iter) : base (iter) {}
  346. protected PrecedingIterator (PrecedingIterator other) : base (other) {}
  347. public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
  348. public override bool MoveNext ()
  349. {
  350. if (_pos == 0)
  351. {
  352. if (_nav.MoveToPrevious ())
  353. {
  354. _pos ++;
  355. return true;
  356. }
  357. }
  358. else
  359. {
  360. if (_nav.MoveToFirstChild ())
  361. {
  362. while (_nav.MoveToNext ())
  363. ;
  364. _pos ++;
  365. return true;
  366. }
  367. do
  368. {
  369. if (_nav.MoveToPrevious ())
  370. {
  371. _pos ++;
  372. return true;
  373. }
  374. }
  375. while (_nav.MoveToParent ());
  376. }
  377. return false;
  378. }
  379. }
  380. internal class NamespaceIterator : SimpleIterator
  381. {
  382. public NamespaceIterator (BaseIterator iter) : base (iter) {}
  383. protected NamespaceIterator (NamespaceIterator other) : base (other) {}
  384. public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
  385. public override bool MoveNext ()
  386. {
  387. if (_pos == 0)
  388. {
  389. if (_nav.MoveToFirstNamespace ())
  390. {
  391. _pos ++;
  392. return true;
  393. }
  394. }
  395. else if (_nav.MoveToNextNamespace ())
  396. {
  397. _pos ++;
  398. return true;
  399. }
  400. return false;
  401. }
  402. }
  403. internal class AttributeIterator : SimpleIterator
  404. {
  405. public AttributeIterator (BaseIterator iter) : base (iter) {}
  406. protected AttributeIterator (AttributeIterator other) : base (other) {}
  407. public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
  408. public override bool MoveNext ()
  409. {
  410. if (_pos == 0)
  411. {
  412. if (_nav.MoveToFirstAttribute ())
  413. {
  414. _pos += 1;
  415. return true;
  416. }
  417. }
  418. else if (_nav.MoveToNextAttribute ())
  419. {
  420. _pos ++;
  421. return true;
  422. }
  423. return false;
  424. }
  425. }
  426. internal class AxisIterator : BaseIterator
  427. {
  428. protected SimpleIterator _iter;
  429. protected NodeTest _test;
  430. protected int _pos;
  431. string name, ns;
  432. XPathNodeType matchType;
  433. public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
  434. {
  435. _iter = iter;
  436. _test = test;
  437. test.GetInfo (out name, out ns, out matchType, NamespaceManager);
  438. if (name != null)
  439. name = Current.NameTable.Add (name);
  440. if (ns != null)
  441. ns = Current.NameTable.Add (ns);
  442. }
  443. protected AxisIterator (AxisIterator other) : base (other)
  444. {
  445. _iter = (SimpleIterator) other._iter.Clone ();
  446. _test = other._test;
  447. _pos = other._pos;
  448. name = other.name;
  449. ns = other.ns;
  450. matchType = other.matchType;
  451. }
  452. public override XPathNodeIterator Clone () { return new AxisIterator (this); }
  453. public override bool MoveNext ()
  454. {
  455. while (_iter.MoveNext ())
  456. {
  457. if (_test.Match (NamespaceManager, Current))
  458. {
  459. _pos ++;
  460. return true;
  461. }
  462. }
  463. return false;
  464. }
  465. public override XPathNavigator Current { get { return _iter.Current; }}
  466. public override int CurrentPosition { get { return _pos; }}
  467. bool Match ()
  468. {
  469. if (Current.NodeType != matchType && matchType != XPathNodeType.All)
  470. return false;
  471. if (ns == null)
  472. return name == null || (object)name == (object)Current.LocalName;
  473. else
  474. return (object)ns == (object)Current.NamespaceURI &&
  475. (name == null || (object)name == (object)Current.LocalName);
  476. }
  477. }
  478. internal class SlashIterator : BaseIterator
  479. {
  480. protected BaseIterator _iterLeft;
  481. protected BaseIterator _iterRight;
  482. protected NodeSet _expr;
  483. protected int _pos;
  484. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  485. {
  486. _iterLeft = iter;
  487. _expr = expr;
  488. }
  489. protected SlashIterator (SlashIterator other) : base (other)
  490. {
  491. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  492. if (other._iterRight != null)
  493. _iterRight = (BaseIterator) other._iterRight.Clone ();
  494. _expr = other._expr;
  495. _pos = other._pos;
  496. }
  497. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  498. public override bool MoveNext ()
  499. {
  500. while (_iterRight == null || !_iterRight.MoveNext ())
  501. {
  502. if (!_iterLeft.MoveNext ())
  503. return false;
  504. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  505. }
  506. _pos ++;
  507. return true;
  508. }
  509. public override XPathNavigator Current {
  510. get {
  511. if (_iterRight == null) return null;
  512. return _iterRight.Current;
  513. }
  514. }
  515. public override int CurrentPosition { get { return _pos; }}
  516. }
  517. internal class PredicateIterator : BaseIterator
  518. {
  519. protected BaseIterator _iter;
  520. protected Expression _pred;
  521. protected int _pos;
  522. protected XPathResultType resType;
  523. public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
  524. {
  525. _iter = iter;
  526. _pred = pred;
  527. resType = pred.GetReturnType (iter);
  528. }
  529. protected PredicateIterator (PredicateIterator other) : base (other)
  530. {
  531. _iter = (BaseIterator) other._iter.Clone ();
  532. _pred = other._pred;
  533. _pos = other._pos;
  534. resType = other.resType;
  535. }
  536. public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
  537. public override bool MoveNext ()
  538. {
  539. while (_iter.MoveNext ())
  540. {
  541. bool fTrue = true;
  542. switch (resType) {
  543. case XPathResultType.Number:
  544. if (_pred.EvaluateNumber (_iter) != _iter.CurrentPosition)
  545. continue;
  546. break;
  547. case XPathResultType.Any: {
  548. object result = _pred.Evaluate (_iter);
  549. if (result is double)
  550. {
  551. if ((double) result != _iter.CurrentPosition)
  552. continue;
  553. }
  554. else if (!XPathFunctions.ToBoolean (result))
  555. continue;
  556. }
  557. break;
  558. default:
  559. if (!_pred.EvaluateBoolean (_iter))
  560. continue;
  561. break;
  562. }
  563. _pos ++;
  564. return true;
  565. }
  566. return false;
  567. }
  568. public override XPathNavigator Current { get { return _iter.Current; }}
  569. public override int CurrentPosition { get { return _pos; }}
  570. }
  571. internal class EnumeratorIterator : BaseIterator
  572. {
  573. protected IEnumerator _enum;
  574. protected int _pos;
  575. public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator) : base (iter)
  576. {
  577. _enum = enumerator;
  578. }
  579. public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm) : base (nsm)
  580. {
  581. _enum = enumerator;
  582. }
  583. protected EnumeratorIterator (EnumeratorIterator other) : base (other)
  584. {
  585. _enum = other._enum;
  586. _pos = other._pos;
  587. }
  588. public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
  589. public override bool MoveNext ()
  590. {
  591. if (!_enum.MoveNext ())
  592. return false;
  593. _pos++;
  594. return true;
  595. }
  596. public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
  597. public override int CurrentPosition { get { return _pos; }}
  598. }
  599. internal class UnionIterator : BaseIterator
  600. {
  601. protected BaseIterator _left, _right;
  602. private int _pos;
  603. private bool keepLeft;
  604. private bool keepRight;
  605. private bool useRight;
  606. public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
  607. {
  608. _left = left;
  609. _right = right;
  610. }
  611. protected UnionIterator (UnionIterator other) : base (other)
  612. {
  613. _left = other._left;
  614. _right = other._right;
  615. _pos = other._pos;
  616. }
  617. public override XPathNodeIterator Clone () { return new UnionIterator (this); }
  618. public override bool MoveNext ()
  619. {
  620. if (!keepLeft)
  621. keepLeft = _left.MoveNext ();
  622. if (!keepRight)
  623. keepRight = _right.MoveNext ();
  624. if (!keepLeft && !keepRight)
  625. return false;
  626. _pos ++;
  627. if (!keepRight) {
  628. keepLeft = useRight = false;
  629. return true;
  630. } else if (!keepLeft) {
  631. keepRight = false;
  632. useRight = true;
  633. return true;
  634. }
  635. switch (_left.Current.ComparePosition (_right.Current)) {
  636. case XmlNodeOrder.Same:
  637. // consume both. i.e. don't output duplicate result.
  638. keepLeft = keepRight = false;
  639. useRight = true;
  640. return true;
  641. case XmlNodeOrder.Before:
  642. keepLeft = useRight = false;
  643. return true;
  644. case XmlNodeOrder.After:
  645. keepRight = false;
  646. useRight = true;
  647. return true;
  648. default:
  649. throw new InvalidOperationException ("Should not happen.");
  650. }
  651. }
  652. public override XPathNavigator Current
  653. {
  654. get
  655. {
  656. if (_pos == 0)
  657. return null;
  658. if (useRight)
  659. return _right.Current;
  660. else
  661. return _left.Current;
  662. }
  663. }
  664. public override int CurrentPosition { get { return _pos; }}
  665. }
  666. }