Expression.cs 30 KB

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