Expression.cs 26 KB

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