Expression.cs 28 KB

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