Iterator.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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. public DescendantIterator (BaseIterator iter) : base (iter) {}
  230. protected DescendantIterator (DescendantIterator other) : base (other)
  231. {
  232. _depth = other._depth;
  233. }
  234. public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
  235. [MonoTODO]
  236. public override bool MoveNext ()
  237. {
  238. if (_nav.MoveToFirstChild ())
  239. {
  240. _depth ++;
  241. _pos ++;
  242. return true;
  243. }
  244. while (_depth != 0)
  245. {
  246. if (_nav.MoveToNext ())
  247. {
  248. _pos ++;
  249. return true;
  250. }
  251. if (!_nav.MoveToParent ()) // should NEVER fail!
  252. throw new XPathException ("unexpected depth"); // TODO: better message
  253. _depth --;
  254. }
  255. return false;
  256. }
  257. }
  258. internal class DescendantOrSelfIterator : SimpleIterator
  259. {
  260. protected int _depth;
  261. private bool _finished;
  262. public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
  263. protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
  264. {
  265. _depth = other._depth;
  266. }
  267. public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
  268. [MonoTODO]
  269. public override bool MoveNext ()
  270. {
  271. if (_finished)
  272. return false;
  273. if (_pos == 0)
  274. {
  275. // self
  276. _pos ++;
  277. return true;
  278. }
  279. if (_nav.MoveToFirstChild ())
  280. {
  281. _depth ++;
  282. _pos ++;
  283. return true;
  284. }
  285. while (_depth != 0)
  286. {
  287. if (_nav.MoveToNext ())
  288. {
  289. _pos ++;
  290. return true;
  291. }
  292. if (!_nav.MoveToParent ()) // should NEVER fail!
  293. throw new XPathException ("unexpected depth"); // TODO: better message
  294. _depth --;
  295. }
  296. _finished = true;
  297. return false;
  298. }
  299. }
  300. internal class FollowingIterator : SimpleIterator
  301. {
  302. public FollowingIterator (BaseIterator iter) : base (iter) {}
  303. protected FollowingIterator (FollowingIterator other) : base (other) {}
  304. public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
  305. public override bool MoveNext ()
  306. {
  307. if (_pos == 0)
  308. {
  309. if (_nav.MoveToNext ())
  310. {
  311. _pos ++;
  312. return true;
  313. }
  314. }
  315. else
  316. {
  317. if (_nav.MoveToFirstChild ())
  318. {
  319. _pos ++;
  320. return true;
  321. }
  322. do
  323. {
  324. if (_nav.MoveToNext ())
  325. {
  326. _pos ++;
  327. return true;
  328. }
  329. }
  330. while (_nav.MoveToParent ());
  331. }
  332. return false;
  333. }
  334. }
  335. internal class PrecedingIterator : SimpleIterator
  336. {
  337. public PrecedingIterator (BaseIterator iter) : base (iter) {}
  338. protected PrecedingIterator (PrecedingIterator other) : base (other) {}
  339. public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
  340. public override bool MoveNext ()
  341. {
  342. if (_pos == 0)
  343. {
  344. if (_nav.MoveToPrevious ())
  345. {
  346. _pos ++;
  347. return true;
  348. }
  349. }
  350. else
  351. {
  352. if (_nav.MoveToFirstChild ())
  353. {
  354. while (_nav.MoveToNext ())
  355. ;
  356. _pos ++;
  357. return true;
  358. }
  359. do
  360. {
  361. if (_nav.MoveToPrevious ())
  362. {
  363. _pos ++;
  364. return true;
  365. }
  366. }
  367. while (_nav.MoveToParent ());
  368. }
  369. return false;
  370. }
  371. }
  372. internal class NamespaceIterator : SimpleIterator
  373. {
  374. public NamespaceIterator (BaseIterator iter) : base (iter) {}
  375. protected NamespaceIterator (NamespaceIterator other) : base (other) {}
  376. public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
  377. public override bool MoveNext ()
  378. {
  379. if (_pos == 0)
  380. {
  381. if (_nav.MoveToFirstNamespace ())
  382. {
  383. _pos ++;
  384. return true;
  385. }
  386. }
  387. else if (_nav.MoveToNextNamespace ())
  388. {
  389. _pos ++;
  390. return true;
  391. }
  392. return false;
  393. }
  394. }
  395. internal class AttributeIterator : SimpleIterator
  396. {
  397. public AttributeIterator (BaseIterator iter) : base (iter) {}
  398. protected AttributeIterator (AttributeIterator other) : base (other) {}
  399. public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
  400. public override bool MoveNext ()
  401. {
  402. if (_pos == 0)
  403. {
  404. if (_nav.MoveToFirstAttribute ())
  405. {
  406. _pos += 1;
  407. return true;
  408. }
  409. }
  410. else if (_nav.MoveToNextAttribute ())
  411. {
  412. _pos ++;
  413. return true;
  414. }
  415. return false;
  416. }
  417. }
  418. internal class AxisIterator : BaseIterator
  419. {
  420. protected SimpleIterator _iter;
  421. protected NodeTest _test;
  422. protected int _pos;
  423. string name, ns;
  424. XPathNodeType matchType;
  425. public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
  426. {
  427. _iter = iter;
  428. _test = test;
  429. test.GetInfo (out name, out ns, out matchType, NamespaceManager);
  430. if (name != null)
  431. name = Current.NameTable.Add (name);
  432. if (ns != null)
  433. ns = Current.NameTable.Add (ns);
  434. }
  435. protected AxisIterator (AxisIterator other) : base (other)
  436. {
  437. _iter = (SimpleIterator) other._iter.Clone ();
  438. _test = other._test;
  439. _pos = other._pos;
  440. name = other.name;
  441. ns = other.ns;
  442. matchType = other.matchType;
  443. }
  444. public override XPathNodeIterator Clone () { return new AxisIterator (this); }
  445. public override bool MoveNext ()
  446. {
  447. while (_iter.MoveNext ())
  448. {
  449. if (_test.Match (NamespaceManager, Current))
  450. {
  451. _pos ++;
  452. return true;
  453. }
  454. }
  455. return false;
  456. }
  457. public override XPathNavigator Current { get { return _iter.Current; }}
  458. public override int CurrentPosition { get { return _pos; }}
  459. bool Match ()
  460. {
  461. if (Current.NodeType != matchType && matchType != XPathNodeType.All)
  462. return false;
  463. if (ns == null)
  464. return name == null || (object)name == (object)Current.LocalName;
  465. else
  466. return (object)ns == (object)Current.NamespaceURI &&
  467. (name == null || (object)name == (object)Current.LocalName);
  468. }
  469. }
  470. internal class SlashIterator : BaseIterator
  471. {
  472. protected BaseIterator _iterLeft;
  473. protected BaseIterator _iterRight;
  474. protected NodeSet _expr;
  475. protected int _pos;
  476. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  477. {
  478. _iterLeft = iter;
  479. _expr = expr;
  480. }
  481. protected SlashIterator (SlashIterator other) : base (other)
  482. {
  483. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  484. if (other._iterRight != null)
  485. _iterRight = (BaseIterator) other._iterRight.Clone ();
  486. _expr = other._expr;
  487. _pos = other._pos;
  488. }
  489. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  490. public override bool MoveNext ()
  491. {
  492. while (_iterRight == null || !_iterRight.MoveNext ())
  493. {
  494. if (!_iterLeft.MoveNext ())
  495. return false;
  496. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  497. }
  498. _pos ++;
  499. return true;
  500. }
  501. public override XPathNavigator Current {
  502. get {
  503. if (_iterRight == null) return null;
  504. return _iterRight.Current;
  505. }
  506. }
  507. public override int CurrentPosition { get { return _pos; }}
  508. }
  509. internal class PredicateIterator : BaseIterator
  510. {
  511. protected BaseIterator _iter;
  512. protected Expression _pred;
  513. protected int _pos;
  514. protected XPathResultType resType;
  515. public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
  516. {
  517. _iter = iter;
  518. _pred = pred;
  519. resType = pred.GetReturnType (iter);
  520. }
  521. protected PredicateIterator (PredicateIterator other) : base (other)
  522. {
  523. _iter = (BaseIterator) other._iter.Clone ();
  524. _pred = other._pred;
  525. _pos = other._pos;
  526. resType = other.resType;
  527. }
  528. public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
  529. public override bool MoveNext ()
  530. {
  531. while (_iter.MoveNext ())
  532. {
  533. bool fTrue = true;
  534. switch (resType) {
  535. case XPathResultType.Number:
  536. if (_pred.EvaluateNumber (_iter) != _iter.CurrentPosition)
  537. continue;
  538. break;
  539. case XPathResultType.Any: {
  540. object result = _pred.Evaluate (_iter);
  541. if (result is double)
  542. {
  543. if ((double) result != _iter.CurrentPosition)
  544. continue;
  545. }
  546. else if (!XPathFunctions.ToBoolean (result))
  547. continue;
  548. }
  549. break;
  550. default:
  551. if (!_pred.EvaluateBoolean (_iter))
  552. continue;
  553. break;
  554. }
  555. _pos ++;
  556. return true;
  557. }
  558. return false;
  559. }
  560. public override XPathNavigator Current { get { return _iter.Current; }}
  561. public override int CurrentPosition { get { return _pos; }}
  562. }
  563. internal class EnumeratorIterator : BaseIterator
  564. {
  565. protected IEnumerator _enum;
  566. protected int _pos;
  567. public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator) : base (iter)
  568. {
  569. _enum = enumerator;
  570. }
  571. public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm) : base (nsm)
  572. {
  573. _enum = enumerator;
  574. }
  575. protected EnumeratorIterator (EnumeratorIterator other) : base (other)
  576. {
  577. _enum = other._enum;
  578. _pos = other._pos;
  579. }
  580. public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
  581. public override bool MoveNext ()
  582. {
  583. if (!_enum.MoveNext ())
  584. return false;
  585. _pos++;
  586. return true;
  587. }
  588. public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
  589. public override int CurrentPosition { get { return _pos; }}
  590. }
  591. internal class UnionIterator : BaseIterator
  592. {
  593. protected BaseIterator _left, _right;
  594. private int _pos;
  595. private bool keepLeft;
  596. private bool keepRight;
  597. private bool useRight;
  598. public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
  599. {
  600. _left = left;
  601. _right = right;
  602. }
  603. protected UnionIterator (UnionIterator other) : base (other)
  604. {
  605. _left = other._left;
  606. _right = other._right;
  607. _pos = other._pos;
  608. }
  609. public override XPathNodeIterator Clone () { return new UnionIterator (this); }
  610. public override bool MoveNext ()
  611. {
  612. if (!keepLeft)
  613. keepLeft = _left.MoveNext ();
  614. if (!keepRight)
  615. keepRight = _right.MoveNext ();
  616. if (!keepLeft && !keepRight)
  617. return false;
  618. _pos ++;
  619. if (!keepRight) {
  620. keepLeft = useRight = false;
  621. return true;
  622. } else if (!keepLeft) {
  623. keepRight = false;
  624. useRight = true;
  625. return true;
  626. }
  627. switch (_left.Current.ComparePosition (_right.Current)) {
  628. case XmlNodeOrder.Same:
  629. // consume both. i.e. don't output duplicate result.
  630. keepLeft = keepRight = false;
  631. useRight = true;
  632. return true;
  633. case XmlNodeOrder.Before:
  634. keepLeft = useRight = false;
  635. return true;
  636. case XmlNodeOrder.After:
  637. keepRight = false;
  638. useRight = true;
  639. return true;
  640. default:
  641. throw new InvalidOperationException ("Should not happen.");
  642. }
  643. }
  644. public override XPathNavigator Current
  645. {
  646. get
  647. {
  648. if (_pos == 0)
  649. return null;
  650. if (useRight)
  651. return _right.Current;
  652. else
  653. return _left.Current;
  654. }
  655. }
  656. public override int CurrentPosition { get { return _pos; }}
  657. }
  658. }