Expression.cs 25 KB

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