Expression.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. //
  2. // System.Xml.XPath.XPathExpression support classes
  3. //
  4. // Author:
  5. // Piers Haken ([email protected])
  6. //
  7. // (C) 2002 Piers Haken
  8. //
  9. using System;
  10. using System.IO;
  11. using System.Collections;
  12. using System.Xml;
  13. using System.Xml.XPath;
  14. using System.Xml.Xsl;
  15. namespace System.Xml.XPath
  16. {
  17. #if XPATH_DEBUG
  18. internal class CompiledExpression : Test.Xml.XPath.XPathExpression
  19. #else
  20. internal class CompiledExpression : XPathExpression
  21. #endif
  22. {
  23. protected XmlNamespaceManager _nsm;
  24. protected Expression _expr;
  25. public CompiledExpression (Expression expr)
  26. {
  27. _expr = expr;
  28. }
  29. private CompiledExpression (CompiledExpression other)
  30. {
  31. _nsm = other._nsm;
  32. _expr = other._expr;
  33. }
  34. #if XPATH_DEBUG
  35. public override Test.Xml.XPath.XPathExpression Clone () { return new CompiledExpression (this); }
  36. #else
  37. public override XPathExpression Clone () { return new CompiledExpression (this); }
  38. #endif
  39. public override void SetContext (XmlNamespaceManager nsManager)
  40. {
  41. _nsm = nsManager;
  42. }
  43. internal XmlNamespaceManager NamespaceManager { get { return _nsm; } }
  44. public override String Expression { get { return _expr.ToString (); }}
  45. public override XPathResultType ReturnType { get { return _expr.ReturnType; }}
  46. [MonoTODO]
  47. public override void AddSort (Object obj, IComparer cmp)
  48. {
  49. throw new NotImplementedException ();
  50. }
  51. [MonoTODO]
  52. public override void AddSort(object obj, XmlSortOrder sortOrder, XmlCaseOrder caseOrder, string str, XmlDataType type)
  53. {
  54. throw new NotImplementedException ();
  55. }
  56. public object Evaluate (BaseIterator iter)
  57. {
  58. try
  59. {
  60. return _expr.Evaluate (iter);
  61. }
  62. catch (XPathException e)
  63. {
  64. throw e;
  65. }
  66. catch (Exception e)
  67. {
  68. throw new XPathException ("Error during evaluation", e);
  69. }
  70. }
  71. public XPathNodeIterator EvaluateNodeSet (BaseIterator iter)
  72. {
  73. try
  74. {
  75. return _expr.EvaluateNodeSet (iter);
  76. }
  77. catch (XPathException e)
  78. {
  79. throw e;
  80. }
  81. catch (Exception e)
  82. {
  83. throw new XPathException ("Error during evaluation", e);
  84. }
  85. }
  86. }
  87. /// <summary>
  88. /// Summary description for Expression.
  89. /// </summary>
  90. internal abstract class Expression
  91. {
  92. private static XsltContext _ctxDefault = new DefaultContext ();
  93. public Expression ()
  94. {
  95. }
  96. public abstract XPathResultType ReturnType { get; }
  97. public virtual XPathResultType GetReturnType (BaseIterator iter) { return ReturnType; }
  98. public virtual object Evaluate (BaseIterator iter) { return null; }
  99. public BaseIterator EvaluateNodeSet (BaseIterator iter)
  100. {
  101. if (GetReturnType (iter) == XPathResultType.NodeSet)
  102. return (BaseIterator) Evaluate (iter);
  103. throw new XPathException ("expected nodeset: "+ToString ());
  104. }
  105. protected static XsltContext DefaultContext { get { return _ctxDefault; } }
  106. [MonoTODO]
  107. public double EvaluateNumber (BaseIterator iter)
  108. {
  109. object result;
  110. XPathResultType type = GetReturnType (iter);
  111. if (type == XPathResultType.NodeSet)
  112. {
  113. result = EvaluateString (iter);
  114. type = XPathResultType.String;
  115. }
  116. else
  117. result = Evaluate (iter);
  118. switch (type)
  119. {
  120. case XPathResultType.Number:
  121. return (double) result;
  122. case XPathResultType.Boolean:
  123. return Convert.ToDouble ((bool) result);
  124. case XPathResultType.String:
  125. return XmlConvert.ToDouble ((string) result); // TODO: spec? convert string to number
  126. default:
  127. throw new XPathException ("invalid node type"); // TODO: handle other types
  128. }
  129. }
  130. [MonoTODO]
  131. public string EvaluateString (BaseIterator iter)
  132. {
  133. object result = Evaluate (iter);
  134. switch (GetReturnType (iter))
  135. {
  136. case XPathResultType.Number:
  137. return (string) XmlConvert.ToString ((double) result); // TODO: spec? convert number to string
  138. case XPathResultType.Boolean:
  139. return ((bool) result) ? "true" : "false";
  140. case XPathResultType.String:
  141. return (string) result;
  142. case XPathResultType.NodeSet:
  143. {
  144. BaseIterator iterResult = (BaseIterator) result;
  145. if (iterResult == null || !iterResult.MoveNext ())
  146. return "";
  147. return iterResult.Current.Value;
  148. }
  149. default:
  150. throw new XPathException ("invalid node type"); // TODO: handle other types
  151. }
  152. }
  153. [MonoTODO]
  154. public bool EvaluateBoolean (BaseIterator iter)
  155. {
  156. object result = Evaluate (iter);
  157. switch (GetReturnType (iter))
  158. {
  159. case XPathResultType.Number:
  160. {
  161. double num = (double) result;
  162. return (num != 0.0 && num != -0.0 && num != Double.NaN);
  163. }
  164. case XPathResultType.Boolean:
  165. return (bool) result;
  166. case XPathResultType.String:
  167. return ((string) result).Length != 0;
  168. case XPathResultType.NodeSet:
  169. {
  170. BaseIterator iterResult = (BaseIterator) result;
  171. return (iterResult != null && iterResult.MoveNext ());
  172. }
  173. default:
  174. throw new XPathException ("invalid node type"); // TODO: handle other types
  175. }
  176. }
  177. public object EvaluateAs (BaseIterator iter, XPathResultType type)
  178. {
  179. switch (type)
  180. {
  181. case XPathResultType.Boolean:
  182. return EvaluateBoolean (iter);
  183. case XPathResultType.NodeSet:
  184. return EvaluateNodeSet (iter);
  185. case XPathResultType.String:
  186. return EvaluateString (iter);
  187. case XPathResultType.Number:
  188. return EvaluateNumber (iter);
  189. }
  190. return Evaluate (iter);
  191. }
  192. }
  193. internal abstract class ExprBinary : Expression
  194. {
  195. protected Expression _left, _right;
  196. public ExprBinary (Expression left, Expression right)
  197. {
  198. _left = left;
  199. _right = right;
  200. }
  201. public override String ToString ()
  202. {
  203. return _left.ToString () + ' ' + Operator + ' ' + _right.ToString ();
  204. }
  205. protected abstract String Operator { get; }
  206. }
  207. internal abstract class ExprBoolean : ExprBinary
  208. {
  209. public ExprBoolean (Expression left, Expression right) : base (left, right) {}
  210. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  211. }
  212. internal class ExprOR : ExprBoolean
  213. {
  214. public ExprOR (Expression left, Expression right) : base (left, right) {}
  215. protected override String Operator { get { return "or"; }}
  216. public override object Evaluate (BaseIterator iter)
  217. {
  218. if (_left.EvaluateBoolean (iter))
  219. return true;
  220. return _right.EvaluateBoolean (iter);
  221. }
  222. }
  223. internal class ExprAND : ExprBoolean
  224. {
  225. public ExprAND (Expression left, Expression right) : base (left, right) {}
  226. protected override String Operator { get { return "and"; }}
  227. public override object Evaluate (BaseIterator iter)
  228. {
  229. if (!_left.EvaluateBoolean (iter))
  230. return false;
  231. return _right.EvaluateBoolean (iter);
  232. }
  233. }
  234. internal abstract class EqualityExpr : ExprBoolean
  235. {
  236. public EqualityExpr (Expression left, Expression right) : base (left, right) {}
  237. [MonoTODO]
  238. public override object Evaluate (BaseIterator iter)
  239. {
  240. XPathResultType typeL = _left.GetReturnType (iter);
  241. XPathResultType typeR = _right.GetReturnType (iter);
  242. if (typeL == XPathResultType.NodeSet || typeR == XPathResultType.NodeSet)
  243. {
  244. Expression left, right;
  245. if (typeL != XPathResultType.NodeSet)
  246. {
  247. left = _right;
  248. right = _left;
  249. XPathResultType typeTmp = typeL;
  250. typeL = typeR;
  251. typeR = typeTmp;
  252. }
  253. else
  254. {
  255. left = _left;
  256. right = _right;
  257. }
  258. if (typeR == XPathResultType.Boolean)
  259. {
  260. bool fL = left.EvaluateBoolean (iter);
  261. bool fR = right.EvaluateBoolean (iter);
  262. return Compare (Convert.ToDouble (fL), Convert.ToDouble (fR));
  263. }
  264. else
  265. {
  266. BaseIterator iterL = left.EvaluateNodeSet (iter);
  267. if (typeR == XPathResultType.Number)
  268. {
  269. double dR = right.EvaluateNumber (iter);
  270. while (iterL.MoveNext ())
  271. if (Compare (XPathFunctions.ToNumber (iterL.Current.Value), dR))
  272. return true;
  273. }
  274. else if (typeR == XPathResultType.String)
  275. {
  276. string strR = right.EvaluateString (iter);
  277. while (iterL.MoveNext ())
  278. if (Compare (iterL.Current.Value, strR))
  279. return true;
  280. }
  281. else if (typeR == XPathResultType.NodeSet)
  282. {
  283. BaseIterator iterR = right.EvaluateNodeSet (iter);
  284. ArrayList rgNodesL = new ArrayList ();
  285. while (iterL.MoveNext ())
  286. rgNodesL.Add (XPathFunctions.ToString (iterL.Current.Value));
  287. while (iterR.MoveNext ())
  288. {
  289. string strR = XPathFunctions.ToString (iterR.Current.Value);
  290. foreach (string strL in rgNodesL)
  291. if (Compare (strL, strR))
  292. return true;
  293. }
  294. }
  295. return false;
  296. }
  297. }
  298. else if (typeL == XPathResultType.Boolean || typeR == XPathResultType.Boolean)
  299. return Compare (_left.EvaluateBoolean (iter), _right.EvaluateBoolean (iter));
  300. else if (typeL == XPathResultType.Number || typeR == XPathResultType.Number)
  301. return Compare (_left.EvaluateNumber (iter), _right.EvaluateNumber (iter));
  302. else
  303. return Compare (_left.EvaluateString (iter), _right.EvaluateString (iter));
  304. }
  305. [MonoTODO]
  306. public abstract bool Compare (object arg1, object arg2); // TODO: should probably have type-safe methods here
  307. }
  308. internal class ExprEQ : EqualityExpr
  309. {
  310. public ExprEQ (Expression left, Expression right) : base (left, right) {}
  311. protected override String Operator { get { return "="; }}
  312. public override bool Compare (object arg1, object arg2)
  313. {
  314. return arg1.Equals (arg2);
  315. }
  316. }
  317. internal class ExprNE : EqualityExpr
  318. {
  319. public ExprNE (Expression left, Expression right) : base (left, right) {}
  320. protected override String Operator { get { return "!="; }}
  321. public override bool Compare (object arg1, object arg2)
  322. {
  323. return !arg1.Equals (arg2);
  324. }
  325. }
  326. internal abstract class RelationalExpr : ExprBoolean
  327. {
  328. public RelationalExpr (Expression left, Expression right) : base (left, right) {}
  329. [MonoTODO]
  330. public override object Evaluate (BaseIterator iter)
  331. {
  332. XPathResultType typeL = _left.GetReturnType (iter);
  333. XPathResultType typeR = _right.GetReturnType (iter);
  334. if (typeL == XPathResultType.NodeSet || typeR == XPathResultType.NodeSet)
  335. {
  336. bool fReverse = false;
  337. Expression left, right;
  338. if (typeL != XPathResultType.NodeSet)
  339. {
  340. fReverse = true;
  341. left = _right;
  342. right = _left;
  343. XPathResultType typeTmp = typeL;
  344. typeL = typeR;
  345. typeR = typeTmp;
  346. }
  347. else
  348. {
  349. left = _left;
  350. right = _right;
  351. }
  352. if (typeR == XPathResultType.Boolean)
  353. {
  354. bool fL = left.EvaluateBoolean (iter);
  355. bool fR = right.EvaluateBoolean (iter);
  356. return Compare (Convert.ToDouble (fL), Convert.ToDouble (fR), fReverse);
  357. }
  358. else
  359. {
  360. BaseIterator iterL = left.EvaluateNodeSet (iter);
  361. if (typeR == XPathResultType.Number || typeR == XPathResultType.String)
  362. {
  363. double dR = right.EvaluateNumber (iter);
  364. while (iterL.MoveNext ())
  365. if (Compare (XPathFunctions.ToNumber (iterL.Current.Value), dR, fReverse))
  366. return true;
  367. }
  368. else if (typeR == XPathResultType.NodeSet)
  369. {
  370. BaseIterator iterR = right.EvaluateNodeSet (iter);
  371. ArrayList rgNodesL = new ArrayList ();
  372. while (iterL.MoveNext ())
  373. rgNodesL.Add (XPathFunctions.ToNumber (iterL.Current.Value));
  374. while (iterR.MoveNext ())
  375. {
  376. double numR = XPathFunctions.ToNumber (iterR.Current.Value);
  377. foreach (double numL in rgNodesL)
  378. if (Compare (numL, numR))
  379. return true;
  380. }
  381. }
  382. return false;
  383. }
  384. }
  385. else
  386. return Compare (_left.EvaluateNumber (iter), _right.EvaluateNumber (iter));
  387. }
  388. public abstract bool Compare (double arg1, double arg2);
  389. public bool Compare (double arg1, double arg2, bool fReverse)
  390. {
  391. if (fReverse)
  392. return Compare (arg2, arg1);
  393. else
  394. return Compare (arg1, arg2);
  395. }
  396. }
  397. internal class ExprGT : RelationalExpr
  398. {
  399. public ExprGT (Expression left, Expression right) : base (left, right) {}
  400. protected override String Operator { get { return ">"; }}
  401. public override bool Compare (double arg1, double arg2)
  402. {
  403. return arg1 > arg2;
  404. }
  405. }
  406. internal class ExprGE : RelationalExpr
  407. {
  408. public ExprGE (Expression left, Expression right) : base (left, right) {}
  409. protected override String Operator { get { return ">="; }}
  410. public override bool Compare (double arg1, double arg2)
  411. {
  412. return arg1 >= arg2;
  413. }
  414. }
  415. internal class ExprLT : RelationalExpr
  416. {
  417. public ExprLT (Expression left, Expression right) : base (left, right) {}
  418. protected override String Operator { get { return "<"; }}
  419. public override bool Compare (double arg1, double arg2)
  420. {
  421. return arg1 < arg2;
  422. }
  423. }
  424. internal class ExprLE : RelationalExpr
  425. {
  426. public ExprLE (Expression left, Expression right) : base (left, right) {}
  427. protected override String Operator { get { return "<="; }}
  428. public override bool Compare (double arg1, double arg2)
  429. {
  430. return arg1 <= arg2;
  431. }
  432. }
  433. internal abstract class ExprNumeric : ExprBinary
  434. {
  435. public ExprNumeric (Expression left, Expression right) : base (left, right) {}
  436. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  437. }
  438. internal class ExprPLUS : ExprNumeric
  439. {
  440. public ExprPLUS (Expression left, Expression right) : base (left, right) {}
  441. protected override String Operator { get { return "+"; }}
  442. public override object Evaluate (BaseIterator iter)
  443. {
  444. return _left.EvaluateNumber (iter) + _right.EvaluateNumber (iter);
  445. }
  446. }
  447. internal class ExprMINUS : ExprNumeric
  448. {
  449. public ExprMINUS (Expression left, Expression right) : base (left, right) {}
  450. protected override String Operator { get { return "-"; }}
  451. public override object Evaluate (BaseIterator iter)
  452. {
  453. return _left.EvaluateNumber (iter) - _right.EvaluateNumber (iter);
  454. }
  455. }
  456. internal class ExprMULT : ExprNumeric
  457. {
  458. public ExprMULT (Expression left, Expression right) : base (left, right) {}
  459. protected override String Operator { get { return "*"; }}
  460. public override object Evaluate (BaseIterator iter)
  461. {
  462. return _left.EvaluateNumber (iter) * _right.EvaluateNumber (iter);
  463. }
  464. }
  465. internal class ExprDIV : ExprNumeric
  466. {
  467. public ExprDIV (Expression left, Expression right) : base (left, right) {}
  468. protected override String Operator { get { return "/"; }}
  469. public override object Evaluate (BaseIterator iter)
  470. {
  471. return _left.EvaluateNumber (iter) / _right.EvaluateNumber (iter);
  472. }
  473. }
  474. internal class ExprMOD : ExprNumeric
  475. {
  476. public ExprMOD (Expression left, Expression right) : base (left, right) {}
  477. protected override String Operator { get { return "%"; }}
  478. [MonoTODO]
  479. public override object Evaluate (BaseIterator iter)
  480. {
  481. return _left.EvaluateNumber (iter) % _right.EvaluateNumber (iter); // TODO: spec?
  482. }
  483. }
  484. internal class ExprNEG : Expression
  485. {
  486. Expression _expr;
  487. public ExprNEG (Expression expr)
  488. {
  489. _expr = expr;
  490. }
  491. public override String ToString () { return "- " + _expr.ToString (); }
  492. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  493. public override object Evaluate (BaseIterator iter)
  494. {
  495. return - _expr.EvaluateNumber (iter);
  496. }
  497. }
  498. internal abstract class NodeSet : Expression
  499. {
  500. public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
  501. }
  502. internal class ExprUNION : NodeSet
  503. {
  504. protected Expression _left, _right;
  505. public ExprUNION (NodeSet left, NodeSet right)
  506. {
  507. _left = left;
  508. _right = right;
  509. }
  510. public override String ToString () { return _left.ToString ()+ " | " + _right.ToString (); }
  511. public override object Evaluate (BaseIterator iter)
  512. {
  513. BaseIterator iterLeft = _left.EvaluateNodeSet (iter);
  514. BaseIterator iterRight = _right.EvaluateNodeSet (iter);
  515. return new UnionIterator (iter, iterLeft, iterRight);
  516. }
  517. }
  518. internal class ExprSLASH : NodeSet
  519. {
  520. protected Expression _left, _right;
  521. public ExprSLASH (Expression left, NodeSet right)
  522. {
  523. _left = left;
  524. _right = right;
  525. }
  526. public override String ToString () { return _left.ToString ()+ "/" + _right.ToString (); }
  527. public override object Evaluate (BaseIterator iter)
  528. {
  529. BaseIterator iterLeft = _left.EvaluateNodeSet (iter);
  530. return new SlashIterator (iterLeft, _right);
  531. }
  532. }
  533. internal class ExprRoot : NodeSet
  534. {
  535. public override String ToString () { return ""; }
  536. public override object Evaluate (BaseIterator iter)
  537. {
  538. XPathNavigator navRoot = iter.Current.Clone ();
  539. navRoot.MoveToRoot ();
  540. return new SelfIterator (navRoot, iter.NamespaceManager);
  541. }
  542. }
  543. internal enum Axes
  544. {
  545. Ancestor,
  546. AncestorOrSelf,
  547. Attribute,
  548. Child,
  549. Descendant,
  550. DescendantOrSelf,
  551. Following,
  552. FollowingSibling,
  553. Namespace,
  554. Parent,
  555. Preceding,
  556. PrecedingSibling,
  557. Self,
  558. }
  559. internal class AxisSpecifier
  560. {
  561. protected Axes _axis;
  562. public AxisSpecifier (Axes axis)
  563. {
  564. _axis = axis;
  565. }
  566. public XPathNodeType NodeType
  567. {
  568. get
  569. {
  570. switch (_axis)
  571. {
  572. case Axes.Namespace:
  573. return XPathNodeType.Namespace;
  574. case Axes.Attribute:
  575. return XPathNodeType.Attribute;
  576. default:
  577. return XPathNodeType.Element;
  578. }
  579. }
  580. }
  581. public override string ToString ()
  582. {
  583. switch (_axis)
  584. {
  585. case Axes.Ancestor:
  586. return "ancestor";
  587. case Axes.AncestorOrSelf:
  588. return "ancestor-or-self";
  589. case Axes.Attribute:
  590. return "attribute";
  591. case Axes.Child:
  592. return "child";
  593. case Axes.Descendant:
  594. return "descendant";
  595. case Axes.DescendantOrSelf:
  596. return "descendant-or-self";
  597. case Axes.Following:
  598. return "following";
  599. case Axes.FollowingSibling:
  600. return "following-sibling";
  601. case Axes.Namespace:
  602. return "namespace";
  603. case Axes.Parent:
  604. return "parent";
  605. case Axes.Preceding:
  606. return "preceeding";
  607. case Axes.PrecedingSibling:
  608. return "preceeding-sibling";
  609. case Axes.Self:
  610. return "self";
  611. default:
  612. throw new IndexOutOfRangeException ();
  613. }
  614. }
  615. public Axes Axis { get { return _axis; }}
  616. public virtual BaseIterator Evaluate (BaseIterator iter)
  617. {
  618. switch (_axis)
  619. {
  620. case Axes.Ancestor:
  621. return new AncestorIterator (iter);
  622. case Axes.AncestorOrSelf:
  623. return new AncestorOrSelfIterator (iter);
  624. case Axes.Attribute:
  625. return new AttributeIterator (iter);
  626. case Axes.Child:
  627. return new ChildIterator (iter);
  628. case Axes.Descendant:
  629. return new DescendantIterator (iter);
  630. case Axes.DescendantOrSelf:
  631. return new DescendantOrSelfIterator (iter);
  632. case Axes.Following:
  633. return new FollowingIterator (iter);
  634. case Axes.FollowingSibling:
  635. return new FollowingSiblingIterator (iter);
  636. case Axes.Namespace:
  637. return new NamespaceIterator (iter);
  638. case Axes.Parent:
  639. return new ParentIterator (iter);
  640. case Axes.Preceding:
  641. return new PrecedingIterator (iter);
  642. case Axes.PrecedingSibling:
  643. return new PrecedingSiblingIterator (iter);
  644. case Axes.Self:
  645. return new SelfIterator (iter);
  646. default:
  647. throw new IndexOutOfRangeException ();
  648. }
  649. }
  650. }
  651. internal abstract class NodeTest
  652. {
  653. protected AxisSpecifier _axis;
  654. public NodeTest (AxisSpecifier axis)
  655. {
  656. _axis = axis;
  657. }
  658. public NodeTest (Axes axis)
  659. {
  660. _axis = new AxisSpecifier (axis);
  661. }
  662. public abstract bool Match (XmlNamespaceManager nsm, XPathNavigator nav);
  663. public AxisSpecifier Axis { get { return _axis; }}
  664. public virtual BaseIterator Evaluate (BaseIterator iter)
  665. {
  666. BaseIterator iterAxis = _axis.Evaluate (iter);
  667. return new AxisIterator (iterAxis, this);
  668. }
  669. }
  670. internal class NodeTypeTest : NodeTest
  671. {
  672. protected XPathNodeType _type;
  673. protected String _param;
  674. public NodeTypeTest (Axes axis) : base (axis)
  675. {
  676. _type = _axis.NodeType;
  677. }
  678. public NodeTypeTest (Axes axis, XPathNodeType type) : base (axis)
  679. {
  680. _type = type;
  681. }
  682. [MonoTODO]
  683. public NodeTypeTest (Axes axis, XPathNodeType type, String param) : base (axis)
  684. {
  685. _type = type;
  686. _param = param;
  687. if (param != null && type != XPathNodeType.ProcessingInstruction)
  688. throw new XPathException ("No argument allowed for "+ToString (_type)+"() test"); // TODO: better description
  689. }
  690. public override String ToString ()
  691. {
  692. String strType = ToString (_type);
  693. if (_type == XPathNodeType.ProcessingInstruction && _param != null)
  694. strType += "('" + _param + "')";
  695. else
  696. strType += "()";
  697. return _axis.ToString () + "::" + strType;
  698. }
  699. private static String ToString (XPathNodeType type)
  700. {
  701. switch (type)
  702. {
  703. case XPathNodeType.Comment:
  704. return "comment";
  705. case XPathNodeType.Text:
  706. return "text";
  707. case XPathNodeType.ProcessingInstruction:
  708. return "processing-instruction";
  709. case XPathNodeType.All:
  710. case XPathNodeType.Attribute:
  711. case XPathNodeType.Element:
  712. return "node";
  713. default:
  714. throw new NotImplementedException ();
  715. }
  716. }
  717. public override bool Match (XmlNamespaceManager nsm, XPathNavigator nav)
  718. {
  719. XPathNodeType nodeType = nav.NodeType;
  720. switch (_type)
  721. {
  722. case XPathNodeType.All:
  723. return true;
  724. case XPathNodeType.ProcessingInstruction:
  725. if (nodeType != XPathNodeType.ProcessingInstruction)
  726. return false;
  727. if (_param != null && nav.Name != _param)
  728. return false;
  729. return true;
  730. default:
  731. return _type == nodeType;
  732. }
  733. }
  734. }
  735. internal class NodeNameTest : NodeTest
  736. {
  737. protected QName _name;
  738. public NodeNameTest (Axes axis, QName name) : base (axis)
  739. {
  740. _name = name;
  741. }
  742. public override String ToString () { return _axis.ToString () + "::" + _name.ToString (); }
  743. [MonoTODO]
  744. public override bool Match (XmlNamespaceManager nsm, XPathNavigator nav)
  745. {
  746. // must be the correct node type
  747. if (nav.NodeType != _axis.NodeType)
  748. return false;
  749. if (_name.Local != null && _name.Local != "")
  750. {
  751. // test the local part of the name first
  752. if (_name.Local != nav.LocalName)
  753. return false;
  754. }
  755. // get the prefix for the given name
  756. String strURI1 = "";
  757. if (_name.Prefix != null && nsm != null)
  758. {
  759. strURI1 = nsm.LookupNamespace (_name.Prefix); // TODO: check to see if this returns null or ""
  760. if (strURI1 == null)
  761. throw new XPathException ("Invalid namespace prefix: "+_name.Prefix);
  762. }
  763. string strURI = nav.NamespaceURI;
  764. if (strURI == null && strURI1 == "") // TODO: remove when bug #26855 fixed
  765. return true;
  766. // test the prefixes
  767. return strURI1 == nav.NamespaceURI;
  768. }
  769. }
  770. internal class ExprStep : NodeSet
  771. {
  772. protected NodeTest _test;
  773. protected Expression [] _preds;
  774. public ExprStep (NodeTest test, ExprPredicates preds)
  775. {
  776. _test = test;
  777. if (preds != null)
  778. _preds = preds.GetPredicates ();
  779. }
  780. public ExprStep (NodeTest test)
  781. {
  782. _test = test;
  783. }
  784. public override String ToString ()
  785. {
  786. String strExpr = _test.ToString ();
  787. if (_preds != null)
  788. {
  789. foreach (Expression pred in _preds)
  790. {
  791. strExpr += '[' + pred.ToString () + ']';
  792. }
  793. }
  794. return strExpr;
  795. }
  796. public override object Evaluate (BaseIterator iter)
  797. {
  798. BaseIterator iterStep = _test.Evaluate (iter);
  799. if (_preds == null)
  800. return iterStep;
  801. return new PredicateIterator (iterStep, _preds);
  802. }
  803. }
  804. internal class ExprPredicates
  805. {
  806. protected Expression _pred;
  807. protected ExprPredicates _tail;
  808. public ExprPredicates (Expression pred, ExprPredicates tail)
  809. {
  810. _pred = pred;
  811. _tail = tail;
  812. }
  813. public ExprPredicates (Expression pred)
  814. {
  815. _pred = pred;
  816. }
  817. public Expression [] GetPredicates ()
  818. {
  819. ArrayList lstPreds = new ArrayList ();
  820. ExprPredicates curr = this;
  821. while (curr != null)
  822. {
  823. lstPreds.Add (curr._pred);
  824. curr = curr._tail;
  825. }
  826. return (Expression []) lstPreds.ToArray (typeof (Expression));
  827. }
  828. }
  829. internal class ExprFilter : Expression
  830. {
  831. protected Expression _expr;
  832. protected Expression _pred;
  833. public ExprFilter (Expression expr, Expression pred)
  834. {
  835. _expr = expr;
  836. _pred = pred;
  837. }
  838. public override String ToString () { return "(" + _expr.ToString () + ")[" + _pred.ToString () + "]"; }
  839. public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
  840. }
  841. internal class QName
  842. {
  843. protected String _prefix;
  844. protected String _local;
  845. public QName (String prefix, String local)
  846. {
  847. _prefix = prefix;
  848. _local = local;
  849. }
  850. public override String ToString ()
  851. {
  852. String strLocal = (_local != null) ? _local : "*";
  853. if (_prefix != null)
  854. return _prefix + ':' + strLocal;
  855. return strLocal;
  856. }
  857. public String Prefix { get { return _prefix; } }
  858. public String Local { get { return _local; } }
  859. }
  860. internal class NCName : QName
  861. {
  862. public NCName (String local) : base (null, local) {}
  863. }
  864. internal class ExprNumber : Expression
  865. {
  866. protected double _value;
  867. public ExprNumber (double value)
  868. {
  869. _value = value;
  870. }
  871. public override String ToString () { return _value.ToString (); }
  872. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  873. public override object Evaluate (BaseIterator iter)
  874. {
  875. return _value;
  876. }
  877. }
  878. internal class ExprLiteral : Expression
  879. {
  880. protected String _value;
  881. public ExprLiteral (String value)
  882. {
  883. _value = value;
  884. }
  885. public override String ToString () { return "'" + _value + "'"; }
  886. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  887. public override object Evaluate (BaseIterator iter)
  888. {
  889. return _value;
  890. }
  891. }
  892. internal class ExprVariable : Expression
  893. {
  894. protected QName _name;
  895. public ExprVariable (QName name)
  896. {
  897. _name = name;
  898. }
  899. public override String ToString () { return "$" + _name.ToString (); }
  900. public override XPathResultType ReturnType { get { return XPathResultType.Any; }}
  901. public override XPathResultType GetReturnType (BaseIterator iter)
  902. {
  903. IXsltContextVariable var = null;
  904. XsltContext context = iter.NamespaceManager as XsltContext;
  905. if (context != null)
  906. var = context.ResolveVariable (_name.Prefix, _name.Local);
  907. if (context == null)
  908. var = DefaultContext.ResolveVariable (_name.Prefix, _name.Local);
  909. if (var == null)
  910. throw new XPathException ("variable "+_name.Prefix+":"+_name.Local+" not found");
  911. return var.VariableType;
  912. }
  913. }
  914. internal class FunctionArguments
  915. {
  916. protected Expression _arg;
  917. protected FunctionArguments _tail;
  918. public FunctionArguments (Expression arg, FunctionArguments tail)
  919. {
  920. _arg = arg;
  921. _tail = tail;
  922. }
  923. public Expression Arg
  924. {
  925. get { return _arg; }
  926. }
  927. public FunctionArguments Tail
  928. {
  929. get { return _tail; }
  930. }
  931. }
  932. internal class ExprFunctionCall : Expression
  933. {
  934. protected QName _name;
  935. protected ArrayList _args = new ArrayList ();
  936. public ExprFunctionCall (String name, FunctionArguments args)
  937. {
  938. _name = new NCName (name);
  939. while (args != null)
  940. {
  941. _args.Add (args.Arg);
  942. args = args.Tail;
  943. }
  944. }
  945. public override String ToString ()
  946. {
  947. String strArgs = "";
  948. foreach (Expression arg in _args)
  949. {
  950. if (strArgs != "")
  951. strArgs += ", ";
  952. strArgs += arg.ToString ();
  953. }
  954. return _name.ToString () + '(' + strArgs + ')';
  955. }
  956. public override XPathResultType ReturnType { get { return XPathResultType.Any; }}
  957. public override XPathResultType GetReturnType (BaseIterator iter)
  958. {
  959. IXsltContextFunction func = null;
  960. XsltContext context = iter.NamespaceManager as XsltContext;
  961. if (context != null)
  962. func = context.ResolveFunction (_name.Prefix, _name.Local, GetArgTypes (iter));
  963. if (func == null)
  964. func = DefaultContext.ResolveFunction (_name.Prefix, _name.Local, GetArgTypes (iter));
  965. if (func == null)
  966. throw new XPathException ("function "+_name.Prefix+":"+_name.Local+" not found");
  967. return func.ReturnType;
  968. }
  969. private XPathResultType [] GetArgTypes (BaseIterator iter)
  970. {
  971. // TODO: can we cache these? what if the types depend on the nsm?
  972. XPathResultType [] rgArgs = new XPathResultType [_args.Count];
  973. for (int iArg = 0; iArg < _args.Count; iArg++)
  974. rgArgs [iArg] = ((Expression) _args [iArg]).GetReturnType (iter);
  975. return rgArgs;
  976. }
  977. public override object Evaluate (BaseIterator iter)
  978. {
  979. //special-case the 'last' and 'position' functions
  980. if (_args.Count == 0 && _name.Prefix == null)
  981. {
  982. if (_name.Local == "last")
  983. {
  984. return (double) iter.Count;
  985. }
  986. else if (_name.Local == "position")
  987. {
  988. return (double) iter.CurrentPosition;
  989. }
  990. }
  991. XPathResultType [] rgTypes = GetArgTypes (iter);
  992. //FIXME: what if func == null after next line?
  993. IXsltContextFunction func = null;
  994. XsltContext context = iter.NamespaceManager as XsltContext;
  995. if (context != null)
  996. func = context.ResolveFunction (_name.Prefix, _name.Local, rgTypes);
  997. if (func == null)
  998. {
  999. context = DefaultContext;
  1000. func = context.ResolveFunction (_name.Prefix, _name.Local, rgTypes);
  1001. }
  1002. if (func == null)
  1003. throw new XPathException ("function "+_name.Prefix+":"+_name.Local+" not found");
  1004. object [] rgArgs = new object [_args.Count];
  1005. if (func.Maxargs != 0)
  1006. {
  1007. XPathResultType [] rgFuncTypes = func.ArgTypes;
  1008. for (int iArg = 0; iArg < _args.Count; iArg ++)
  1009. {
  1010. XPathResultType typeArg = (iArg < rgFuncTypes.Length) ? rgFuncTypes [iArg] : rgFuncTypes [rgFuncTypes.Length - 1];
  1011. rgArgs [iArg] = ((Expression) _args [iArg]).EvaluateAs (iter, typeArg);
  1012. }
  1013. }
  1014. return func.Invoke (context, rgArgs, iter.Current);
  1015. }
  1016. }
  1017. }