XPathSequence.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626
  1. //
  2. // XPathSequence.cs - represents XPath sequence iterator
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. //
  8. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. #if NET_2_0
  30. using System;
  31. using System.Collections;
  32. using System.Xml;
  33. using System.Xml.Schema;
  34. using System.Xml.Query;
  35. using System.Xml.XPath;
  36. namespace Mono.Xml.XPath2
  37. {
  38. public abstract class XPathSequence : IEnumerable, ICloneable
  39. {
  40. XQueryContext ctx;
  41. int countCache = -1;
  42. int position = 0;
  43. internal XPathSequence (XQueryContext ctx)
  44. {
  45. this.ctx = ctx;
  46. }
  47. internal XPathSequence (XPathSequence original)
  48. {
  49. ctx = original.ctx;
  50. position = original.position;
  51. }
  52. internal XQueryContext Context {
  53. // get { return ctx; }
  54. get { return ctx.ContextManager.CurrentContext; }
  55. }
  56. public virtual int Count {
  57. get {
  58. if (countCache >= 0)
  59. return countCache;
  60. XPathSequence clone = Clone ();
  61. while (clone.MoveNext ())
  62. ;
  63. countCache = clone.Position;
  64. return countCache;
  65. }
  66. }
  67. public XPathItem Current {
  68. get {
  69. if (Position == 0)
  70. throw new InvalidOperationException ("XQuery internal error (should not happen)");
  71. return CurrentCore;
  72. }
  73. }
  74. public abstract XPathItem CurrentCore { get; }
  75. // Returns 0 if not started, otherwise returns XPath positional integer.
  76. public virtual int Position {
  77. get { return position; }
  78. }
  79. public virtual bool MoveNext ()
  80. {
  81. if (!MoveNextCore ())
  82. return false;
  83. position++;
  84. return true;
  85. }
  86. protected abstract bool MoveNextCore ();
  87. public abstract XPathSequence Clone ();
  88. object ICloneable.Clone ()
  89. {
  90. return this.Clone ();
  91. }
  92. public virtual IEnumerator GetEnumerator ()
  93. {
  94. while (MoveNext ())
  95. yield return CurrentCore;
  96. }
  97. }
  98. // empty iterator (still required since it contains XQueryContext)
  99. class XPathEmptySequence : XPathSequence
  100. {
  101. internal XPathEmptySequence (XQueryContext ctx)
  102. : base (ctx)
  103. {
  104. }
  105. public override int Count {
  106. get { return 0; }
  107. }
  108. protected override bool MoveNextCore ()
  109. {
  110. return false;
  111. }
  112. public override XPathItem CurrentCore {
  113. get { throw new InvalidOperationException ("Should not happen. In XPathEmptySequence.Current."); }
  114. }
  115. // Don't return clone. It's waste of resource.
  116. public override XPathSequence Clone ()
  117. {
  118. return this;
  119. }
  120. }
  121. // single item iterator
  122. internal class SingleItemIterator : XPathSequence
  123. {
  124. XPathItem item;
  125. XPathItem current;
  126. // for XQuery execution start point
  127. internal SingleItemIterator (XPathItem item, XQueryContext ctx)
  128. : base (ctx)
  129. {
  130. this.item = item;
  131. }
  132. private SingleItemIterator (SingleItemIterator other)
  133. : base (other)
  134. {
  135. this.item = other.item;
  136. this.current = other.current;
  137. }
  138. public override XPathSequence Clone ()
  139. {
  140. return new SingleItemIterator (this);
  141. }
  142. protected override bool MoveNextCore ()
  143. {
  144. if (current == null) {
  145. current = item;
  146. return true;
  147. }
  148. return false;
  149. }
  150. public override XPathItem CurrentCore {
  151. get {
  152. return current;
  153. }
  154. }
  155. }
  156. // RangeExpr iterator
  157. internal class IntegerRangeIterator : XPathSequence
  158. {
  159. static XmlSchemaSimpleType intType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("int", XmlSchema.Namespace));
  160. int start;
  161. int end;
  162. int next;
  163. XPathItem current;
  164. public IntegerRangeIterator (XQueryContext ctx, int start, int end)
  165. : base (ctx)
  166. {
  167. this.start = start;
  168. this.end = end;
  169. }
  170. private IntegerRangeIterator (IntegerRangeIterator other)
  171. : base (other)
  172. {
  173. this.start = other.start;
  174. this.end = other.end;
  175. this.next = other.next;
  176. this.current = other.current;
  177. }
  178. public override XPathSequence Clone ()
  179. {
  180. return new IntegerRangeIterator (this);
  181. }
  182. protected override bool MoveNextCore ()
  183. {
  184. if (current == null)
  185. next = start;
  186. if (next > end)
  187. return false;
  188. current = new XPathAtomicValue (next++, intType);
  189. return true;
  190. }
  191. public override XPathItem CurrentCore {
  192. get {
  193. return current;
  194. }
  195. }
  196. }
  197. // Slash iterator
  198. // <copy original='System.Xml.XPath/Iterator.cs,
  199. // System.Xml.XPath/XPathComparer.cs'>
  200. internal class PathStepIterator : XPathSequence
  201. {
  202. XPathSequence left;
  203. XPathSequence right;
  204. PathStepExpr step;
  205. ArrayList nodeStore;
  206. SortedList storedIterators;
  207. bool finished;
  208. XPathSequence nextRight;
  209. public PathStepIterator (XPathSequence iter, PathStepExpr source)
  210. : base (iter.Context)
  211. {
  212. left = iter;
  213. step = source;
  214. }
  215. private PathStepIterator (PathStepIterator other)
  216. : base (other)
  217. {
  218. left = other.left.Clone ();
  219. step = other.step;
  220. if (other.right != null)
  221. right = other.right.Clone ();
  222. if (other.nodeStore != null)
  223. nodeStore = (ArrayList) other.nodeStore.Clone ();
  224. if (other.storedIterators != null)
  225. storedIterators = (SortedList) other.storedIterators.Clone ();
  226. if (other.nextRight != null)
  227. nextRight = other.nextRight.Clone ();
  228. }
  229. public override XPathSequence Clone ()
  230. {
  231. return new PathStepIterator (this);
  232. }
  233. protected override bool MoveNextCore ()
  234. {
  235. if (finished)
  236. return false;
  237. if (step.RequireSorting) {
  238. // Mainly '//' ('/descendant-or-self::node()/')
  239. if (nodeStore == null) {
  240. CollectResults ();
  241. if (nodeStore.Count == 0) {
  242. finished = true;
  243. return false;
  244. }
  245. }
  246. if (nodeStore.Count == Position) {
  247. finished = true;
  248. return false;
  249. }
  250. while (nodeStore.Count > Position) {
  251. if (((XPathNavigator) nodeStore [Position]).ComparePosition (
  252. (XPathNavigator) nodeStore [Position - 1]) == XmlNodeOrder.Same)
  253. nodeStore.RemoveAt (Position);
  254. else
  255. break;
  256. }
  257. return true;
  258. } else { // Sorting not required
  259. if (right == null) { // First time
  260. if (!left.MoveNext ())
  261. return false;
  262. right = step.Next.Evaluate (left);
  263. storedIterators = new SortedList (XPathSequenceComparer.Instance);
  264. }
  265. while (true) {
  266. while (!right.MoveNext ()) {
  267. if (storedIterators.Count > 0) {
  268. int last = storedIterators.Count - 1;
  269. XPathSequence tmpIter = (XPathSequence) storedIterators.GetByIndex (last);
  270. storedIterators.RemoveAt (last);
  271. switch (((XPathNavigator) tmpIter.Current).ComparePosition ((XPathNavigator) right.Current)) {
  272. case XmlNodeOrder.Same:
  273. case XmlNodeOrder.Before:
  274. right = tmpIter;
  275. continue;
  276. default:
  277. right = tmpIter;
  278. break;
  279. }
  280. break;
  281. } else if (nextRight != null) {
  282. right = nextRight;
  283. nextRight = null;
  284. break;
  285. } else if (!left.MoveNext ()) {
  286. finished = true;
  287. return false;
  288. }
  289. else
  290. right = step.Next.Evaluate (left);
  291. }
  292. bool loop = true;
  293. while (loop) {
  294. loop = false;
  295. if (nextRight == null) {
  296. bool noMoreNext = false;
  297. while (nextRight == null || !nextRight.MoveNext ()) {
  298. if(left.MoveNext ())
  299. nextRight = step.Next.Evaluate (left);
  300. else {
  301. noMoreNext = true;
  302. break;
  303. }
  304. }
  305. if (noMoreNext)
  306. nextRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  307. }
  308. if (nextRight != null) {
  309. switch (((XPathNavigator) right.Current).ComparePosition ((XPathNavigator) nextRight.Current)) {
  310. case XmlNodeOrder.After:
  311. storedIterators.Add (storedIterators.Count, right);
  312. right = nextRight;
  313. nextRight = null;
  314. loop = true;
  315. break;
  316. case XmlNodeOrder.Same:
  317. if (!nextRight.MoveNext ())
  318. nextRight = null;
  319. else {
  320. int last = storedIterators.Count;
  321. if (last > 0) {
  322. storedIterators.Add (last, nextRight);
  323. nextRight = (XPathSequence) storedIterators.GetByIndex (last);
  324. storedIterators.RemoveAt (last);
  325. }
  326. }
  327. loop = true;
  328. break;
  329. }
  330. }
  331. }
  332. return true;
  333. }
  334. }
  335. }
  336. private void CollectResults ()
  337. {
  338. if (nodeStore != null)
  339. return;
  340. nodeStore = new ArrayList ();
  341. while (true) {
  342. while (right == null || !right.MoveNext ()) {
  343. if (!left.MoveNext ()) {
  344. nodeStore.Sort (XPathNavigatorComparer2.Instance);
  345. return;
  346. }
  347. right = step.Next.Evaluate (left);
  348. }
  349. XPathNavigator nav = (XPathNavigator) right.Current;
  350. nodeStore.Add (nav);
  351. }
  352. }
  353. public override XPathItem CurrentCore {
  354. get {
  355. if (Position <= 0) return null;
  356. if (step.RequireSorting) {
  357. return (XPathNavigator) nodeStore [Position - 1];
  358. } else {
  359. return right.Current;
  360. }
  361. }
  362. }
  363. public override int Count {
  364. get {
  365. if (nodeStore == null)
  366. return base.Count;
  367. else
  368. return nodeStore.Count;
  369. }
  370. }
  371. internal class XPathSequenceComparer : IComparer
  372. {
  373. public static XPathSequenceComparer Instance = new XPathSequenceComparer ();
  374. private XPathSequenceComparer ()
  375. {
  376. }
  377. public int Compare (object o1, object o2)
  378. {
  379. XPathSequence nav1 = o1 as XPathSequence;
  380. XPathSequence nav2 = o2 as XPathSequence;
  381. if (nav1 == null)
  382. return -1;
  383. if (nav2 == null)
  384. return 1;
  385. switch (((XPathNavigator) nav1.Current).ComparePosition ((XPathNavigator) nav2.Current)) {
  386. case XmlNodeOrder.Same:
  387. return 0;
  388. case XmlNodeOrder.After:
  389. return -1;
  390. default:
  391. return 1;
  392. }
  393. }
  394. }
  395. internal class XPathNavigatorComparer2 : IComparer
  396. {
  397. public static XPathNavigatorComparer2 Instance = new XPathNavigatorComparer2 ();
  398. private XPathNavigatorComparer2 ()
  399. {
  400. }
  401. public int Compare (object o1, object o2)
  402. {
  403. XPathNavigator nav1 = o1 as XPathNavigator;
  404. XPathNavigator nav2 = o2 as XPathNavigator;
  405. if (nav1 == null)
  406. return -1;
  407. if (nav2 == null)
  408. return 1;
  409. switch (nav1.ComparePosition (nav2)) {
  410. case XmlNodeOrder.Same:
  411. return 0;
  412. case XmlNodeOrder.After:
  413. return 1;
  414. default:
  415. return -1;
  416. }
  417. }
  418. }
  419. }
  420. // </copy>
  421. // Filter step iterator
  422. internal class FilteredIterator : XPathSequence
  423. {
  424. XPathSequence left;
  425. PredicateList filter;
  426. public FilteredIterator (XPathSequence iter, FilterStepExpr source)
  427. : base (iter.Context)
  428. {
  429. left = source.Expr.Evaluate (iter);
  430. filter = source.Predicates;
  431. }
  432. private FilteredIterator (FilteredIterator other)
  433. : base (other)
  434. {
  435. left = other.left.Clone ();
  436. filter = other.filter;
  437. }
  438. public override XPathSequence Clone ()
  439. {
  440. return new FilteredIterator (this);
  441. }
  442. protected override bool MoveNextCore ()
  443. {
  444. while (left.MoveNext ()) {
  445. bool skipThisItem = false;
  446. // Examine all filters
  447. foreach (ExprSequence expr in filter) {
  448. bool doesntPass = true;
  449. // Treat as OK if any of expr passed.
  450. // FIXME: handle numeric predicate.
  451. foreach (ExprSingle single in expr) {
  452. if (single.EvaluateAsBoolean (left)) {
  453. doesntPass = false;
  454. break;
  455. }
  456. }
  457. if (doesntPass) {
  458. skipThisItem = true;
  459. break;
  460. }
  461. }
  462. if (skipThisItem)
  463. continue;
  464. return true;
  465. }
  466. return false;
  467. }
  468. public override XPathItem CurrentCore {
  469. get { return left.Current; }
  470. }
  471. }
  472. // AxisIterator
  473. internal class AxisIterator : XPathSequence
  474. {
  475. NodeIterator iter;
  476. AxisStepExpr source;
  477. public AxisIterator (NodeIterator iter, AxisStepExpr source)
  478. : base (iter.Context)
  479. {
  480. this.iter = iter;
  481. this.source = source;
  482. }
  483. private AxisIterator (AxisIterator other)
  484. : base (other)
  485. {
  486. iter = (NodeIterator) other.iter.Clone ();
  487. source = other.source;
  488. }
  489. public override XPathSequence Clone ()
  490. {
  491. return new AxisIterator (this);
  492. }
  493. protected override bool MoveNextCore ()
  494. {
  495. while (iter.MoveNext ()) {
  496. if (source.Matches (iter.Current as XPathNavigator))
  497. return true;
  498. }
  499. return false;
  500. }
  501. public override XPathItem CurrentCore {
  502. get { return iter.Current; }
  503. }
  504. }
  505. internal abstract class NodeIterator : XPathSequence
  506. {
  507. XPathNavigator node;
  508. XPathNavigator current;
  509. bool emptyInput;
  510. public NodeIterator (XPathNavigator nav, XQueryContext ctx)
  511. : base (ctx)
  512. {
  513. this.node = nav.Clone ();
  514. }
  515. /*
  516. public NodeIterator (XPathSequence iter)
  517. : base (iter.Context)
  518. {
  519. if (iter.Position == 0) {
  520. if (!iter.MoveNext ()) {
  521. emptyInput = true;
  522. return;
  523. }
  524. }
  525. XPathItem item = iter.Current;
  526. node = item as XPathNavigator;
  527. if (node == null)
  528. throw new XmlQueryException (String.Format ("Current item is expected to be a node, but it is {0} ({1}).", item.XmlType.QualifiedName, item.XmlType.TypeCode));
  529. node = node.Clone ();
  530. }
  531. */
  532. internal NodeIterator (NodeIterator other, bool cloneFlag)
  533. : base (other)
  534. {
  535. if (other.emptyInput)
  536. emptyInput = true;
  537. else
  538. node = other.node.Clone ();
  539. }
  540. internal XPathNavigator Node {
  541. get { return node; }
  542. }
  543. public override bool MoveNext ()
  544. {
  545. if (emptyInput)
  546. return false;
  547. if (!base.MoveNext ())
  548. return false;
  549. current = null;
  550. return true;
  551. }
  552. public override XPathItem CurrentCore {
  553. get {
  554. if (current == null)
  555. current = node.Clone ();
  556. return current;
  557. }
  558. }
  559. public virtual bool ReverseAxis {
  560. get { return false; }
  561. }
  562. }
  563. // <copy original='System.Xml.XPath/Iterator.cs'>
  564. internal class SelfIterator : NodeIterator
  565. {
  566. public SelfIterator (XPathNavigator nav, XQueryContext ctx)
  567. : base (nav, ctx)
  568. {
  569. }
  570. private SelfIterator (SelfIterator other, bool cloneFlag)
  571. : base (other, true)
  572. {
  573. }
  574. public override XPathSequence Clone ()
  575. {
  576. return new SelfIterator (this, true);
  577. }
  578. protected override bool MoveNextCore ()
  579. {
  580. if (Position == 0)
  581. return true;
  582. return false;
  583. }
  584. }
  585. internal class ParentIterator : NodeIterator
  586. {
  587. public ParentIterator (XPathNavigator nav, XQueryContext ctx)
  588. : base (nav, ctx)
  589. {
  590. }
  591. private ParentIterator (ParentIterator other, bool cloneFlag)
  592. : base (other, true)
  593. {
  594. }
  595. public override XPathSequence Clone ()
  596. {
  597. return new ParentIterator (this, true);
  598. }
  599. protected override bool MoveNextCore ()
  600. {
  601. if (Position == 0 && Node.MoveToParent ())
  602. return true;
  603. return false;
  604. }
  605. public override bool ReverseAxis {
  606. get { return true; }
  607. }
  608. }
  609. internal class ChildIterator : NodeIterator
  610. {
  611. public ChildIterator (XPathNavigator nav, XQueryContext ctx)
  612. : base (nav, ctx)
  613. {
  614. }
  615. private ChildIterator (ChildIterator other, bool cloneFlag)
  616. : base (other, true)
  617. {
  618. }
  619. public override XPathSequence Clone ()
  620. {
  621. return new ChildIterator (this, true);
  622. }
  623. protected override bool MoveNextCore ()
  624. {
  625. if (Position == 0)
  626. return Node.MoveToFirstChild ();
  627. else
  628. return Node.MoveToNext ();
  629. }
  630. }
  631. internal class FollowingSiblingIterator : NodeIterator
  632. {
  633. public FollowingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
  634. : base (nav, ctx)
  635. {
  636. }
  637. private FollowingSiblingIterator (FollowingSiblingIterator other, bool cloneFlag)
  638. : base (other, true)
  639. {
  640. }
  641. public override XPathSequence Clone ()
  642. {
  643. return new FollowingSiblingIterator (this, true);
  644. }
  645. protected override bool MoveNextCore ()
  646. {
  647. return Node.MoveToNext ();
  648. }
  649. }
  650. internal class PrecedingSiblingIterator : NodeIterator
  651. {
  652. bool finished;
  653. bool started;
  654. XPathNavigator startPosition;
  655. public PrecedingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
  656. : base (nav, ctx)
  657. {
  658. startPosition = Node.Clone ();
  659. }
  660. private PrecedingSiblingIterator (PrecedingSiblingIterator other, bool cloneFlag)
  661. : base (other, true)
  662. {
  663. startPosition = other.startPosition;
  664. started = other.started;
  665. finished = other.finished;
  666. }
  667. public override XPathSequence Clone ()
  668. {
  669. return new PrecedingSiblingIterator (this, true);
  670. }
  671. protected override bool MoveNextCore ()
  672. {
  673. if (finished)
  674. return false;
  675. if (!started) {
  676. started = true;
  677. Node.MoveToFirst ();
  678. } else {
  679. Node.MoveToNext ();
  680. }
  681. if (Node.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  682. finished = true;
  683. return false;
  684. }
  685. else
  686. return true;
  687. }
  688. public override bool ReverseAxis {
  689. get { return true; }
  690. }
  691. }
  692. internal class AncestorIterator : NodeIterator
  693. {
  694. bool finished;
  695. ArrayList nodes = new ArrayList ();
  696. public AncestorIterator (XPathNavigator nav, XQueryContext ctx)
  697. : base (nav, ctx)
  698. {
  699. }
  700. private AncestorIterator (AncestorIterator other, bool cloneFlag)
  701. : base (other, true)
  702. {
  703. finished = other.finished;
  704. nodes = other.nodes;
  705. }
  706. public override XPathSequence Clone ()
  707. {
  708. return new AncestorIterator (this, true);
  709. }
  710. protected override bool MoveNextCore ()
  711. {
  712. if (finished)
  713. return false;
  714. if (nodes != null) {
  715. nodes = new ArrayList ();
  716. while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root)
  717. nodes.Add (Node.Clone ());
  718. nodes.Reverse ();
  719. }
  720. if (nodes.Count >= Position)
  721. return false;
  722. Node.MoveTo (nodes [Position] as XPathNavigator);
  723. return true;
  724. }
  725. public override bool ReverseAxis {
  726. get { return true; }
  727. }
  728. public override int Count {
  729. get {
  730. if (Position == 0)
  731. return base.Count;
  732. return nodes.Count;
  733. }
  734. }
  735. }
  736. internal class AncestorOrSelfIterator : NodeIterator
  737. {
  738. bool finished;
  739. ArrayList nodes = new ArrayList ();
  740. public AncestorOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
  741. : base (nav, ctx)
  742. {
  743. }
  744. private AncestorOrSelfIterator (AncestorOrSelfIterator other, bool cloneFlag)
  745. : base (other, true)
  746. {
  747. finished = other.finished;
  748. nodes = other.nodes;
  749. }
  750. public override XPathSequence Clone ()
  751. {
  752. return new AncestorOrSelfIterator (this, true);
  753. }
  754. protected override bool MoveNextCore ()
  755. {
  756. if (finished)
  757. return false;
  758. if (nodes != null) {
  759. nodes = new ArrayList ();
  760. do {
  761. nodes.Add (Node.Clone ());
  762. } while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root);
  763. nodes.Reverse ();
  764. }
  765. if (nodes.Count >= Position)
  766. return false;
  767. Node.MoveTo (nodes [Position] as XPathNavigator);
  768. return true;
  769. }
  770. public override bool ReverseAxis {
  771. get { return true; }
  772. }
  773. public override int Count {
  774. get {
  775. if (Position == 0)
  776. return base.Count;
  777. return nodes.Count;
  778. }
  779. }
  780. }
  781. internal class DescendantIterator : NodeIterator
  782. {
  783. private int depth;
  784. private bool finished;
  785. public DescendantIterator (XPathNavigator nav, XQueryContext ctx)
  786. : base (nav, ctx)
  787. {
  788. }
  789. private DescendantIterator (DescendantIterator other, bool cloneFlag)
  790. : base (other, true)
  791. {
  792. finished = other.finished;
  793. depth = other.depth;
  794. }
  795. public override XPathSequence Clone ()
  796. {
  797. return new DescendantIterator (this, true);
  798. }
  799. protected override bool MoveNextCore ()
  800. {
  801. if (finished)
  802. return false;
  803. if (Node.MoveToFirstChild ()) {
  804. depth ++;
  805. return true;
  806. }
  807. while (depth != 0) {
  808. if (Node.MoveToNext ())
  809. return true;
  810. if (!Node.MoveToParent ()) // should NEVER fail!
  811. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  812. depth --;
  813. }
  814. finished = true;
  815. return false;
  816. }
  817. }
  818. internal class DescendantOrSelfIterator : NodeIterator
  819. {
  820. protected int depth;
  821. private bool finished;
  822. public DescendantOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
  823. : base (nav, ctx)
  824. {
  825. }
  826. protected DescendantOrSelfIterator (DescendantOrSelfIterator other, bool cloneFlag)
  827. : base (other, true)
  828. {
  829. depth = other.depth;
  830. finished = other.finished;
  831. }
  832. public override XPathSequence Clone ()
  833. {
  834. return new DescendantOrSelfIterator (this, true);
  835. }
  836. protected override bool MoveNextCore ()
  837. {
  838. if (finished)
  839. return false;
  840. if (Position == 0)
  841. return true; // Self
  842. if (Node.MoveToFirstChild ()) {
  843. depth ++;
  844. return true;
  845. }
  846. while (depth != 0) {
  847. if (Node.MoveToNext ())
  848. return true;
  849. if (!Node.MoveToParent ()) // should NEVER fail!
  850. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  851. depth --;
  852. }
  853. finished = true;
  854. return false;
  855. }
  856. }
  857. internal class FollowingIterator : NodeIterator
  858. {
  859. private bool finished;
  860. public FollowingIterator (XPathNavigator nav, XQueryContext ctx)
  861. : base (nav, ctx)
  862. {
  863. }
  864. protected FollowingIterator (FollowingIterator other, bool cloneFlag)
  865. : base (other, true)
  866. {
  867. finished = other.finished;
  868. }
  869. public override XPathSequence Clone ()
  870. {
  871. return new FollowingIterator (this, true);
  872. }
  873. protected override bool MoveNextCore ()
  874. {
  875. if (finished)
  876. return false;
  877. if (Position == 0) {
  878. // At first, it should not iterate children.
  879. if (Node.MoveToNext ())
  880. return true;
  881. else {
  882. while (Node.MoveToParent ())
  883. if (Node.MoveToNext ())
  884. return true;
  885. }
  886. } else {
  887. if (Node.MoveToFirstChild ())
  888. return true;
  889. do {
  890. if (Node.MoveToNext ())
  891. return true;
  892. } while (Node.MoveToParent ());
  893. }
  894. finished = true;
  895. return false;
  896. }
  897. }
  898. internal class PrecedingIterator : NodeIterator
  899. {
  900. bool finished;
  901. bool started;
  902. XPathNavigator startPosition;
  903. public PrecedingIterator (XPathNavigator nav, XQueryContext ctx)
  904. : base (nav, ctx)
  905. {
  906. startPosition = Node.Clone ();
  907. }
  908. private PrecedingIterator (PrecedingIterator other, bool cloneFlag)
  909. : base (other, true)
  910. {
  911. startPosition = other.startPosition;
  912. started = other.started;
  913. finished = other.finished;
  914. }
  915. public override XPathSequence Clone ()
  916. {
  917. return new PrecedingIterator (this, true);
  918. }
  919. protected override bool MoveNextCore ()
  920. {
  921. if (finished)
  922. return false;
  923. if (!started) {
  924. started = true;
  925. Node.MoveToRoot ();
  926. }
  927. bool loop = true;
  928. while (loop) {
  929. while (!Node.MoveToFirstChild ()) {
  930. while (!Node.MoveToNext ()) {
  931. if (!Node.MoveToParent ()) { // Should not finish, at least before startPosition.
  932. finished = true;
  933. return false;
  934. }
  935. }
  936. break;
  937. }
  938. if (Node.IsDescendant (startPosition))
  939. continue;
  940. loop = false;
  941. break;
  942. }
  943. if (Node.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  944. // Note that if _nav contains only 1 node, it won't be Same.
  945. finished = true;
  946. return false;
  947. }
  948. else
  949. return true;
  950. }
  951. public override bool ReverseAxis {
  952. get { return true; }
  953. }
  954. }
  955. internal class NamespaceIterator : NodeIterator
  956. {
  957. public NamespaceIterator (XPathNavigator nav, XQueryContext ctx)
  958. : base (nav, ctx)
  959. {
  960. }
  961. private NamespaceIterator (NamespaceIterator other, bool cloneFlag)
  962. : base (other, true)
  963. {
  964. }
  965. public override XPathSequence Clone ()
  966. {
  967. return new NamespaceIterator (this, true);
  968. }
  969. protected override bool MoveNextCore ()
  970. {
  971. if (Position == 0) {
  972. if (Node.MoveToFirstNamespace ())
  973. return true;
  974. }
  975. else if (Node.MoveToNextNamespace ())
  976. return true;
  977. return false;
  978. }
  979. public override bool ReverseAxis { get { return true; } }
  980. }
  981. internal class AttributeIterator : NodeIterator
  982. {
  983. public AttributeIterator (XPathNavigator nav, XQueryContext ctx)
  984. : base (nav, ctx)
  985. {
  986. }
  987. private AttributeIterator (AttributeIterator other, bool cloneFlag)
  988. : base (other, true)
  989. {
  990. }
  991. public override XPathSequence Clone ()
  992. {
  993. return new AttributeIterator (this, true);
  994. }
  995. protected override bool MoveNextCore ()
  996. {
  997. if (Position == 0) {
  998. if (Node.MoveToFirstAttribute ())
  999. return true;
  1000. }
  1001. else if (Node.MoveToNextAttribute ())
  1002. return true;
  1003. return false;
  1004. }
  1005. }
  1006. // </copy>
  1007. internal class ExprSequenceIterator : XPathSequence
  1008. {
  1009. XPathSequence contextSequence;
  1010. XPathSequence iter;
  1011. ExprSequence expr;
  1012. int currentExprIndex;
  1013. public ExprSequenceIterator (XPathSequence iter, ExprSequence expr)
  1014. : base (iter.Context)
  1015. {
  1016. contextSequence = iter;
  1017. this.expr = expr;
  1018. }
  1019. private ExprSequenceIterator (ExprSequenceIterator other)
  1020. : base (other)
  1021. {
  1022. if (other.iter != null)
  1023. iter = other.iter.Clone ();
  1024. expr = other.expr;
  1025. contextSequence = other.contextSequence;
  1026. currentExprIndex = other.currentExprIndex;
  1027. }
  1028. public override XPathSequence Clone ()
  1029. {
  1030. return new ExprSequenceIterator (this);
  1031. }
  1032. protected override bool MoveNextCore ()
  1033. {
  1034. if (iter != null && iter.MoveNext ())
  1035. return true;
  1036. while (currentExprIndex < expr.Count) {
  1037. iter = expr [currentExprIndex++].Evaluate (contextSequence);
  1038. if (iter.MoveNext ())
  1039. return true;
  1040. }
  1041. return false;
  1042. }
  1043. public override XPathItem CurrentCore {
  1044. get { return iter.Current; }
  1045. }
  1046. }
  1047. // FLWOR - Order By
  1048. internal class FLWORIterator : XPathSequence
  1049. {
  1050. XPathSequence contextSequence;
  1051. FLWORExpr expr;
  1052. ArrayList forStack = new ArrayList ();
  1053. IEnumerator en;
  1054. bool finished;
  1055. public FLWORIterator (XPathSequence iter, FLWORExpr expr)
  1056. : base (iter.Context)
  1057. {
  1058. this.contextSequence = iter;
  1059. this.expr = expr;
  1060. }
  1061. private FLWORIterator (FLWORIterator other)
  1062. : base (other)
  1063. {
  1064. contextSequence = other.contextSequence;
  1065. expr = other.expr;
  1066. forStack = other.forStack.Clone () as ArrayList;
  1067. if (en != null)
  1068. en = ((ICloneable) other.en).Clone () as IEnumerator;
  1069. finished = other.finished;
  1070. }
  1071. public override XPathSequence Clone ()
  1072. {
  1073. return new FLWORIterator (this);
  1074. }
  1075. protected override bool MoveNextCore ()
  1076. {
  1077. if (en == null)
  1078. en = GetEnumerator ();
  1079. return en.MoveNext ();
  1080. }
  1081. public override IEnumerator GetEnumerator ()
  1082. {
  1083. IEnumerator forLetEnum = expr.ForLetClauses.GetEnumerator ();
  1084. // FIXME: this invokation seems to result in an Invalid IL error.
  1085. return EvaluateRemainingForLet (forLetEnum);
  1086. }
  1087. private IEnumerator EvaluateRemainingForLet (IEnumerator forLetEnum)
  1088. {
  1089. // Prepare iteration stack
  1090. if (forLetEnum.MoveNext ()) {
  1091. ForLetClause flc = (ForLetClause) forLetEnum.Current;
  1092. IEnumerator flsb = flc.GetEnumerator ();
  1093. IEnumerator items = EvaluateRemainingSingleItem (forLetEnum, flsb);
  1094. while (items.MoveNext ())
  1095. yield return items.Current;
  1096. yield break;
  1097. }
  1098. bool passedFilter = expr.WhereClause == null;
  1099. if (!passedFilter)
  1100. passedFilter = expr.WhereClause.EvaluateAsBoolean (contextSequence);
  1101. if (passedFilter) {
  1102. IEnumerator ie = expr.ReturnExpr.Evaluate (contextSequence).GetEnumerator ();
  1103. while (ie.MoveNext ())
  1104. yield return (XPathItem) ie.Current;
  1105. }
  1106. }
  1107. private IEnumerator EvaluateRemainingSingleItem (IEnumerator forLetClauses, IEnumerator singleBodies)
  1108. {
  1109. if (singleBodies.MoveNext ()) {
  1110. ForLetSingleBody sb = singleBodies.Current as ForLetSingleBody;
  1111. ForSingleBody fsb = sb as ForSingleBody;
  1112. if (fsb != null) {
  1113. XPathSequence backup = contextSequence;
  1114. contextSequence = sb.Expression.Evaluate (Context.CurrentSequence);
  1115. Context.ContextManager.PushCurrentSequence (contextSequence);
  1116. while (contextSequence.MoveNext ()) {
  1117. XPathItem forItem = (XPathItem) contextSequence.Current;
  1118. Context.PushVariable (fsb.PositionalVar, contextSequence.Position);
  1119. Context.PushVariable (sb.VarName, forItem);
  1120. // recurse here (including following bindings)
  1121. IEnumerator items =
  1122. EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1123. while (items.MoveNext ())
  1124. yield return (XPathItem) items.Current;
  1125. Context.PopVariable ();
  1126. Context.PopVariable ();
  1127. }
  1128. Context.ContextManager.PopCurrentSequence ();
  1129. contextSequence = backup;
  1130. } else {
  1131. Context.PushVariable (sb.VarName, sb.Expression.Evaluate (contextSequence));
  1132. // recurse here (including following bindings)
  1133. IEnumerator items = EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1134. while (items.MoveNext ())
  1135. yield return (XPathItem) items.Current;
  1136. Context.PopVariable ();
  1137. }
  1138. } else {
  1139. // examine next binding
  1140. IEnumerator items = EvaluateRemainingForLet (forLetClauses);
  1141. while (items.MoveNext ())
  1142. yield return (XPathItem) items.Current;
  1143. }
  1144. }
  1145. public override XPathItem CurrentCore {
  1146. get { return (XPathItem) en.Current; }
  1147. }
  1148. }
  1149. internal class GroupIterator : XPathSequence
  1150. {
  1151. GroupExpr expr;
  1152. XPathSequence lseq;
  1153. XPathSequence rseq;
  1154. bool started;
  1155. bool left;
  1156. bool leftFinished;
  1157. bool rightFinished;
  1158. public GroupIterator (XPathSequence iter, GroupExpr expr)
  1159. : base (iter.Context)
  1160. {
  1161. this.expr = expr;
  1162. left = true;
  1163. lseq = expr.Left.EvaluateOrdered (iter);
  1164. rseq = expr.Right.EvaluateOrdered (iter);
  1165. }
  1166. private GroupIterator (GroupIterator other)
  1167. : base (other)
  1168. {
  1169. this.expr = other.expr;
  1170. this.started = other.started;
  1171. this.left = other.left;
  1172. this.leftFinished = other.leftFinished;
  1173. this.rightFinished = other.rightFinished;
  1174. this.lseq = other.lseq.Clone ();
  1175. this.rseq = other.rseq.Clone ();
  1176. }
  1177. public override XPathSequence Clone ()
  1178. {
  1179. return new GroupIterator (this);
  1180. }
  1181. protected override bool MoveNextCore ()
  1182. {
  1183. if (leftFinished && rightFinished)
  1184. return false;
  1185. bool proceeded = false;
  1186. if (started) {
  1187. if (left) {
  1188. if (!leftFinished && lseq.MoveNext ())
  1189. proceeded = true;
  1190. else
  1191. leftFinished = true;
  1192. } else {
  1193. if (rightFinished && rseq.MoveNext ())
  1194. proceeded = true;
  1195. else
  1196. rightFinished = true;
  1197. }
  1198. } else {
  1199. started = true;
  1200. if (!lseq.MoveNext ()) {
  1201. leftFinished = true;
  1202. if (!rseq.MoveNext ()) {
  1203. rightFinished = true;
  1204. return false;
  1205. }
  1206. left = false;
  1207. return true;
  1208. }
  1209. proceeded = true;
  1210. if (!rseq.MoveNext ()) {
  1211. rightFinished = true;
  1212. return true;
  1213. }
  1214. }
  1215. if (!proceeded) {
  1216. if (expr.AggregationType == AggregationType.Intersect)
  1217. return false;
  1218. left = !leftFinished;
  1219. return !leftFinished || !rightFinished;
  1220. }
  1221. XPathNavigator lnav = lseq.Current as XPathNavigator;
  1222. XPathNavigator rnav = rseq.Current as XPathNavigator;
  1223. if (lnav == null || rnav == null)
  1224. throw new XmlQueryException ("XP0006: Evaluation against union, intersect, except expressions must result in nodes.");
  1225. XmlNodeOrder order = lnav.ComparePosition (rnav);
  1226. switch (order) {
  1227. case XmlNodeOrder.Same:
  1228. switch (expr.AggregationType) {
  1229. case AggregationType.Union:
  1230. left = false;
  1231. if (!lseq.MoveNext ())
  1232. leftFinished = true;
  1233. return true;
  1234. case AggregationType.Intersect:
  1235. return true;
  1236. case AggregationType.Except:
  1237. default:
  1238. return MoveNext ();
  1239. }
  1240. case XmlNodeOrder.Before:
  1241. left = true;
  1242. if (expr.AggregationType == AggregationType.Intersect)
  1243. return MoveNext ();
  1244. return true;
  1245. default: // After, Unknown
  1246. left = false;
  1247. if (expr.AggregationType == AggregationType.Intersect)
  1248. return MoveNext ();
  1249. return true;
  1250. }
  1251. }
  1252. public override XPathItem CurrentCore {
  1253. get { return left ? lseq.Current : rseq.Current; }
  1254. }
  1255. }
  1256. internal class AtomizingIterator : XPathSequence
  1257. {
  1258. XPathSequence iter;
  1259. public AtomizingIterator (XPathSequence iter)
  1260. : base (iter.Context)
  1261. {
  1262. this.iter = iter;
  1263. }
  1264. private AtomizingIterator (AtomizingIterator other)
  1265. : base (other)
  1266. {
  1267. iter = other.iter.Clone ();
  1268. }
  1269. public override XPathSequence Clone ()
  1270. {
  1271. return new AtomizingIterator (this);
  1272. }
  1273. protected override bool MoveNextCore ()
  1274. {
  1275. return iter.MoveNext ();
  1276. }
  1277. public override XPathItem CurrentCore {
  1278. get {
  1279. XPathNavigator nav = iter.Current as XPathNavigator;
  1280. if (nav == null)
  1281. return (XPathAtomicValue) iter.Current;
  1282. if (nav.SchemaInfo != null)
  1283. return new XPathAtomicValue (
  1284. nav.TypedValue,
  1285. nav.SchemaInfo.SchemaType);
  1286. else
  1287. return new XPathAtomicValue (nav.Value, null);
  1288. }
  1289. }
  1290. }
  1291. internal class ConvertingIterator : XPathSequence
  1292. {
  1293. XPathSequence iter;
  1294. SequenceType type;
  1295. public ConvertingIterator (XPathSequence iter, SequenceType type)
  1296. : base (iter.Context)
  1297. {
  1298. this.iter = iter;
  1299. this.type = type;
  1300. }
  1301. private ConvertingIterator (ConvertingIterator other)
  1302. : base (other)
  1303. {
  1304. iter = other.iter.Clone ();
  1305. type = other.type;
  1306. }
  1307. public override XPathSequence Clone ()
  1308. {
  1309. return new ConvertingIterator (this);
  1310. }
  1311. protected override bool MoveNextCore ()
  1312. {
  1313. return iter.MoveNext ();
  1314. }
  1315. public override XPathItem CurrentCore {
  1316. get { return type.Convert (iter.Current); }
  1317. }
  1318. }
  1319. internal class TracingIterator : XPathSequence
  1320. {
  1321. XPathSequence iter;
  1322. string format;
  1323. public TracingIterator (XPathSequence iter, string format)
  1324. : base (iter.Context)
  1325. {
  1326. this.iter = iter;
  1327. this.format = format;
  1328. }
  1329. private TracingIterator (TracingIterator other)
  1330. : base (other)
  1331. {
  1332. iter = other.iter.Clone ();
  1333. format = other.format;
  1334. }
  1335. public override XPathSequence Clone ()
  1336. {
  1337. return new TracingIterator (this);
  1338. }
  1339. protected override bool MoveNextCore ()
  1340. {
  1341. if (!iter.MoveNext ())
  1342. return false;
  1343. // FIXME: use OnMessageEvent
  1344. string output = String.Format (format, iter.Current.TypedValue);
  1345. Context.StaticContext.OnMessageEvent (iter.Current, new TraceEventArgs (output));
  1346. return true;
  1347. }
  1348. public override XPathItem CurrentCore {
  1349. get { return iter.Current; }
  1350. }
  1351. internal class TraceEventArgs : QueryEventArgs
  1352. {
  1353. string message;
  1354. internal TraceEventArgs (string message)
  1355. {
  1356. this.message = message;
  1357. }
  1358. public override string Message {
  1359. get { return message; }
  1360. }
  1361. }
  1362. }
  1363. internal class ListIterator : XPathSequence
  1364. {
  1365. IList list;
  1366. public ListIterator (XPathSequence iter, IList list)
  1367. : base (iter.Context)
  1368. {
  1369. if (list is ICloneable)
  1370. this.list = list;
  1371. else
  1372. throw new InvalidOperationException (String.Format ("XQuery internal error: target list is not cloneable. List is {0}.", list != null ? list.GetType ().ToString () : "null argument"));
  1373. }
  1374. private ListIterator (ListIterator other)
  1375. : base (other)
  1376. {
  1377. this.list = (IList) ((ICloneable) other.list).Clone ();
  1378. }
  1379. public override XPathSequence Clone ()
  1380. {
  1381. return new ListIterator (this);
  1382. }
  1383. protected override bool MoveNextCore ()
  1384. {
  1385. return (Position < list.Count);
  1386. }
  1387. public override XPathItem CurrentCore {
  1388. get { return (XPathItem) list [Position - 1]; }
  1389. }
  1390. }
  1391. internal class EnumeratorIterator : XPathSequence
  1392. {
  1393. IEnumerator list;
  1394. public EnumeratorIterator (XQueryContext ctx, IEnumerable en)
  1395. : base (ctx)
  1396. {
  1397. list = en.GetEnumerator ();
  1398. if (list is ICloneable)
  1399. this.list = list;
  1400. else
  1401. throw new InvalidOperationException (String.Format ("XQuery internal error: target list's enumerator is not cloneable. List is {0}.", en != null ? en.GetType ().ToString () : "null argument"));
  1402. }
  1403. private EnumeratorIterator (EnumeratorIterator other)
  1404. : base (other)
  1405. {
  1406. this.list = (IEnumerator) ((ICloneable) other.list).Clone ();
  1407. }
  1408. public override XPathSequence Clone ()
  1409. {
  1410. return new EnumeratorIterator (this);
  1411. }
  1412. protected override bool MoveNextCore ()
  1413. {
  1414. return list.MoveNext ();
  1415. }
  1416. public override XPathItem CurrentCore {
  1417. get { return (XPathItem) list.Current; }
  1418. }
  1419. }
  1420. }
  1421. #endif