DefaultContext.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. //
  2. // System.Xml.XPath.DefaultContext & support classes
  3. //
  4. // Author:
  5. // Piers Haken ([email protected])
  6. //
  7. // (C) 2002 Piers Haken
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Xml;
  12. using System.Xml.XPath;
  13. using System.Xml.Xsl;
  14. using System.Text;
  15. namespace System.Xml.XPath
  16. {
  17. internal class XPathFunctions
  18. {
  19. public static bool ToBoolean (object arg)
  20. {
  21. if (arg == null)
  22. throw new ArgumentNullException ();
  23. if (arg is bool)
  24. return (bool) arg;
  25. if (arg is double)
  26. {
  27. double dArg = (double) arg;
  28. return (dArg != 0.0 && !double.IsNaN (dArg));
  29. }
  30. if (arg is string)
  31. return ((string) arg).Length != 0;
  32. if (arg is BaseIterator)
  33. {
  34. BaseIterator iter = (BaseIterator) arg;
  35. return iter.MoveNext ();
  36. }
  37. throw new ArgumentException ();
  38. }
  39. [MonoTODO]
  40. public static string ToString (object arg)
  41. {
  42. if (arg == null)
  43. throw new ArgumentNullException ();
  44. if (arg is string)
  45. return (string) arg;
  46. if (arg is bool)
  47. return ((bool) arg) ? "true" : "false";
  48. if (arg is double)
  49. return ((double) arg).ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
  50. if (arg is BaseIterator)
  51. {
  52. BaseIterator iter = (BaseIterator) arg;
  53. if (!iter.MoveNext ())
  54. return "";
  55. return iter.Current.Value;
  56. }
  57. throw new ArgumentException ();
  58. }
  59. [MonoTODO]
  60. public static double ToNumber (object arg)
  61. {
  62. if (arg == null)
  63. throw new ArgumentNullException ();
  64. if (arg is BaseIterator)
  65. arg = ToString (arg); // follow on
  66. if (arg is string)
  67. {
  68. string s = arg as string;
  69. if (s.Length == 0)
  70. return double.NaN;
  71. try
  72. {
  73. return XmlConvert.ToDouble (s); // TODO: spec? convert string to number
  74. }
  75. catch (System.FormatException)
  76. {
  77. return double.NaN;
  78. }
  79. }
  80. if (arg is double)
  81. return (double) arg;
  82. if (arg is bool)
  83. return Convert.ToDouble ((bool) arg);
  84. throw new ArgumentException ();
  85. }
  86. public static double ToNumber (string arg)
  87. {
  88. if (arg == null)
  89. throw new ArgumentNullException ();
  90. if (arg.Length == 0)
  91. return double.NaN;
  92. try {
  93. return XmlConvert.ToDouble ((string) arg.Trim (XmlChar.WhitespaceChars));
  94. } catch (System.OverflowException) {
  95. return double.NaN;
  96. } catch (System.FormatException) {
  97. return double.NaN;
  98. }
  99. }
  100. }
  101. internal abstract class XPathFunction : Expression
  102. {
  103. public XPathFunction (FunctionArguments args) {}
  104. }
  105. internal class XPathFunctionLast : XPathFunction
  106. {
  107. public XPathFunctionLast (FunctionArguments args) : base (args)
  108. {
  109. if (args != null)
  110. throw new XPathException ("last takes 0 args");
  111. }
  112. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  113. public override object Evaluate (BaseIterator iter)
  114. {
  115. return (double) iter.Count;
  116. }
  117. public override string ToString ()
  118. {
  119. return "last()";
  120. }
  121. }
  122. internal class XPathFunctionPosition : XPathFunction
  123. {
  124. public XPathFunctionPosition (FunctionArguments args) : base (args)
  125. {
  126. if (args != null)
  127. throw new XPathException ("position takes 0 args");
  128. }
  129. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  130. public override object Evaluate (BaseIterator iter)
  131. {
  132. return (double) iter.CurrentPosition;
  133. }
  134. public override string ToString ()
  135. {
  136. return "position()";
  137. }
  138. }
  139. internal class XPathFunctionCount : XPathFunction
  140. {
  141. Expression arg0;
  142. public XPathFunctionCount (FunctionArguments args) : base (args)
  143. {
  144. if (args == null || args.Tail != null)
  145. throw new XPathException ("count takes 1 arg");
  146. arg0 = args.Arg;
  147. }
  148. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  149. public override object Evaluate (BaseIterator iter)
  150. {
  151. return (double) arg0.EvaluateNodeSet (iter).Count;
  152. }
  153. public override bool EvaluateBoolean (BaseIterator iter)
  154. {
  155. if (arg0.GetReturnType (iter) == XPathResultType.NodeSet)
  156. return arg0.EvaluateBoolean (iter);
  157. return arg0.EvaluateNodeSet (iter).MoveNext ();
  158. }
  159. public override string ToString ()
  160. {
  161. return "count(" + arg0.ToString () + ")";
  162. }
  163. }
  164. internal class XPathFunctionId : XPathFunction
  165. {
  166. Expression arg0;
  167. public XPathFunctionId (FunctionArguments args) : base (args)
  168. {
  169. if (args == null || args.Tail != null)
  170. throw new XPathException ("id takes 1 arg");
  171. arg0 = args.Arg;
  172. }
  173. public Expression Id { get { return arg0; } }
  174. private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
  175. public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
  176. public override object Evaluate (BaseIterator iter)
  177. {
  178. String strArgs;
  179. object val = arg0.Evaluate (iter);
  180. BaseIterator valItr = val as BaseIterator;
  181. if (valItr != null)
  182. {
  183. strArgs = "";
  184. while (valItr.MoveNext ())
  185. strArgs += valItr.Current.Value + " ";
  186. }
  187. else
  188. strArgs = XPathFunctions.ToString (val);
  189. XPathNavigator n = iter.Current.Clone ();
  190. ArrayList rgNodes = new ArrayList ();
  191. string [] ids = strArgs.Split (rgchWhitespace);
  192. for (int i = 0; i < ids.Length; i++)
  193. if (n.MoveToId (ids [i]))
  194. rgNodes.Add (n.Clone ());
  195. rgNodes.Sort (XPathNavigatorComparer.Instance);
  196. return new EnumeratorIterator (iter, rgNodes.GetEnumerator ());
  197. }
  198. public override string ToString ()
  199. {
  200. return "id(" + arg0.ToString () + ")";
  201. }
  202. }
  203. internal class XPathFunctionLocalName : XPathFunction
  204. {
  205. Expression arg0;
  206. public XPathFunctionLocalName (FunctionArguments args) : base (args)
  207. {
  208. if (args != null) {
  209. arg0 = args.Arg;
  210. if (args.Tail != null)
  211. throw new XPathException ("local-name takes 1 or zero args");
  212. }
  213. }
  214. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  215. public override object Evaluate (BaseIterator iter)
  216. {
  217. if (arg0 == null)
  218. return iter.Current.LocalName;
  219. BaseIterator argNs = arg0.EvaluateNodeSet (iter);
  220. if (argNs == null || !argNs.MoveNext ())
  221. return "";
  222. return argNs.Current.LocalName;
  223. }
  224. public override string ToString ()
  225. {
  226. return "local-name(" + arg0.ToString () + ")";
  227. }
  228. }
  229. internal class XPathFunctionNamespaceUri : XPathFunction
  230. {
  231. Expression arg0;
  232. public XPathFunctionNamespaceUri (FunctionArguments args) : base (args)
  233. {
  234. if (args != null) {
  235. arg0 = args.Arg;
  236. if (args.Tail != null)
  237. throw new XPathException ("namespace-uri takes 1 or zero args");
  238. }
  239. }
  240. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  241. public override object Evaluate (BaseIterator iter)
  242. {
  243. if (arg0 == null)
  244. return iter.Current.NamespaceURI;
  245. BaseIterator argNs = arg0.EvaluateNodeSet (iter);
  246. if (argNs == null || !argNs.MoveNext ())
  247. return "";
  248. return argNs.Current.NamespaceURI;
  249. }
  250. public override string ToString ()
  251. {
  252. return "namespace-uri(" + arg0.ToString () + ")";
  253. }
  254. }
  255. internal class XPathFunctionName : XPathFunction
  256. {
  257. Expression arg0;
  258. public XPathFunctionName (FunctionArguments args) : base (args)
  259. {
  260. if (args != null) {
  261. arg0 = args.Arg;
  262. if (args.Tail != null)
  263. throw new XPathException ("name takes 1 or zero args");
  264. }
  265. }
  266. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  267. public override object Evaluate (BaseIterator iter)
  268. {
  269. if (arg0 == null)
  270. return iter.Current.Name;
  271. BaseIterator argNs = arg0.EvaluateNodeSet (iter);
  272. if (argNs == null || !argNs.MoveNext ())
  273. return "";
  274. return argNs.Current.Name;
  275. }
  276. public override string ToString ()
  277. {
  278. return "name(" + arg0.ToString () + ")";
  279. }
  280. }
  281. internal class XPathFunctionString : XPathFunction
  282. {
  283. Expression arg0;
  284. public XPathFunctionString (FunctionArguments args) : base (args)
  285. {
  286. if (args != null) {
  287. arg0 = args.Arg;
  288. if (args.Tail != null)
  289. throw new XPathException ("boolean takes 1 or zero args");
  290. }
  291. }
  292. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  293. public override object Evaluate (BaseIterator iter)
  294. {
  295. if (arg0 == null)
  296. return iter.Current.Value;
  297. return arg0.EvaluateString (iter);
  298. }
  299. public override string ToString ()
  300. {
  301. return "string(" + arg0.ToString () + ")";
  302. }
  303. }
  304. internal class XPathFunctionConcat : XPathFunction
  305. {
  306. ArrayList rgs;
  307. public XPathFunctionConcat (FunctionArguments args) : base (args)
  308. {
  309. if (args == null || args.Tail == null)
  310. throw new XPathException ("concat takes 2 or more args");
  311. args.ToArrayList (rgs = new ArrayList ());
  312. }
  313. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  314. public override object Evaluate (BaseIterator iter)
  315. {
  316. StringBuilder sb = new StringBuilder ();
  317. int len = rgs.Count;
  318. for (int i = 0; i < len; i++)
  319. sb.Append (((Expression)rgs[i]).EvaluateString (iter));
  320. return sb.ToString ();
  321. }
  322. public override string ToString ()
  323. {
  324. StringBuilder sb = new StringBuilder ();
  325. sb.Append ("concat(");
  326. for (int i = 0; i < rgs.Count - 1; i++) {
  327. sb.Append (rgs [i].ToString ());
  328. sb.Append (',');
  329. }
  330. sb.Append (rgs [rgs.Count - 1].ToString ());
  331. sb.Append (')');
  332. return sb.ToString ();
  333. }
  334. }
  335. internal class XPathFunctionStartsWith : XPathFunction
  336. {
  337. Expression arg0, arg1;
  338. public XPathFunctionStartsWith (FunctionArguments args) : base (args)
  339. {
  340. if (args == null || args.Tail == null || args.Tail.Tail != null)
  341. throw new XPathException ("starts-with takes 2 args");
  342. arg0 = args.Arg;
  343. arg1 = args.Tail.Arg;
  344. }
  345. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  346. public override object Evaluate (BaseIterator iter)
  347. {
  348. return arg0.EvaluateString (iter).StartsWith (arg1.EvaluateString (iter));
  349. }
  350. public override string ToString ()
  351. {
  352. return String.Concat ("starts-with(", arg0.ToString (), ",", arg1.ToString (), ")");
  353. }
  354. }
  355. internal class XPathFunctionContains : XPathFunction
  356. {
  357. Expression arg0, arg1;
  358. public XPathFunctionContains (FunctionArguments args) : base (args)
  359. {
  360. if (args == null || args.Tail == null || args.Tail.Tail != null)
  361. throw new XPathException ("contains takes 2 args");
  362. arg0 = args.Arg;
  363. arg1 = args.Tail.Arg;
  364. }
  365. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  366. public override object Evaluate (BaseIterator iter)
  367. {
  368. return arg0.EvaluateString (iter).IndexOf (arg1.EvaluateString (iter)) != -1;
  369. }
  370. public override string ToString ()
  371. {
  372. return String.Concat ("contains(", arg0.ToString (), ",", arg1.ToString (), ")");
  373. }
  374. }
  375. internal class XPathFunctionSubstringBefore : XPathFunction
  376. {
  377. Expression arg0, arg1;
  378. public XPathFunctionSubstringBefore (FunctionArguments args) : base (args)
  379. {
  380. if (args == null || args.Tail == null || args.Tail.Tail != null)
  381. throw new XPathException ("substring-before takes 2 args");
  382. arg0 = args.Arg;
  383. arg1 = args.Tail.Arg;
  384. }
  385. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  386. public override object Evaluate (BaseIterator iter)
  387. {
  388. string str1 = arg0.EvaluateString (iter);
  389. string str2 = arg1.EvaluateString (iter);
  390. int ich = str1.IndexOf (str2);
  391. if (ich <= 0)
  392. return "";
  393. return str1.Substring (0, ich);
  394. }
  395. public override string ToString ()
  396. {
  397. return String.Concat ("substring-before(", arg0.ToString (), ",", arg1.ToString (), ")");
  398. }
  399. }
  400. internal class XPathFunctionSubstringAfter : XPathFunction
  401. {
  402. Expression arg0, arg1;
  403. public XPathFunctionSubstringAfter (FunctionArguments args) : base (args)
  404. {
  405. if (args == null || args.Tail == null || args.Tail.Tail != null)
  406. throw new XPathException ("substring-after takes 2 args");
  407. arg0 = args.Arg;
  408. arg1 = args.Tail.Arg;
  409. }
  410. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  411. public override object Evaluate (BaseIterator iter)
  412. {
  413. string str1 = arg0.EvaluateString (iter);
  414. string str2 = arg1.EvaluateString (iter);
  415. int ich = str1.IndexOf (str2);
  416. if (ich < 0)
  417. return "";
  418. return str1.Substring (ich + str2.Length);
  419. }
  420. public override string ToString ()
  421. {
  422. return String.Concat ("substring-after(", arg0.ToString (), ",", arg1.ToString (), ")");
  423. }
  424. }
  425. internal class XPathFunctionSubstring : XPathFunction
  426. {
  427. Expression arg0, arg1, arg2;
  428. public XPathFunctionSubstring (FunctionArguments args) : base (args)
  429. {
  430. if (args == null || args.Tail == null || (args.Tail.Tail != null && args.Tail.Tail.Tail != null))
  431. throw new XPathException ("substring takes 2 or 3 args");
  432. arg0 = args.Arg;
  433. arg1 = args.Tail.Arg;
  434. if (args.Tail.Tail != null)
  435. arg2= args.Tail.Tail.Arg;
  436. }
  437. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  438. public override object Evaluate (BaseIterator iter)
  439. {
  440. string str = arg0.EvaluateString (iter);
  441. double ich = Math.Round (arg1.EvaluateNumber (iter)) - 1;
  442. if (Double.IsNaN (ich) ||
  443. Double.IsNegativeInfinity (ich) ||
  444. ich >= (double) str.Length)
  445. return "";
  446. if (arg2 == null)
  447. {
  448. if (ich < 0)
  449. ich = 0.0;
  450. return str.Substring ((int) ich);
  451. }
  452. else
  453. {
  454. double cch = Math.Round (arg2.EvaluateNumber (iter));
  455. if (Double.IsNaN (cch))
  456. return "";
  457. if (ich < 0.0 || cch < 0.0)
  458. {
  459. cch = ich + cch;
  460. if (cch <= 0.0)
  461. return "";
  462. ich = 0.0;
  463. }
  464. double cchMax = (double) str.Length - ich;
  465. if (cch > cchMax)
  466. cch = cchMax;
  467. return str.Substring ((int) ich, (int) cch);
  468. }
  469. }
  470. public override string ToString ()
  471. {
  472. return String.Concat (new string [] {
  473. "substring(", arg0.ToString (), ",", arg1.ToString (), ",", arg2.ToString (), ")"});
  474. }
  475. }
  476. internal class XPathFunctionStringLength : XPathFunction
  477. {
  478. Expression arg0;
  479. public XPathFunctionStringLength (FunctionArguments args) : base (args)
  480. {
  481. if (args != null) {
  482. arg0 = args.Arg;
  483. if (args.Tail != null)
  484. throw new XPathException ("string-length takes 1 or zero args");
  485. }
  486. }
  487. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  488. public override object Evaluate (BaseIterator iter)
  489. {
  490. string str;
  491. if (arg0 != null)
  492. str = arg0.EvaluateString (iter);
  493. else
  494. str = iter.Current.Value;
  495. return (double) str.Length;
  496. }
  497. public override string ToString ()
  498. {
  499. return String.Concat (new string [] {
  500. "string-length(", arg0.ToString (), ")"});
  501. }
  502. }
  503. internal class XPathFunctionNormalizeSpace : XPathFunction
  504. {
  505. Expression arg0;
  506. public XPathFunctionNormalizeSpace (FunctionArguments args) : base (args)
  507. {
  508. if (args != null) {
  509. arg0 = args.Arg;
  510. if (args.Tail != null)
  511. throw new XPathException ("normalize-space takes 1 or zero args");
  512. }
  513. }
  514. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  515. public override object Evaluate (BaseIterator iter)
  516. {
  517. string str;
  518. if (arg0 != null)
  519. str = arg0.EvaluateString (iter);
  520. else
  521. str = iter.Current.Value;
  522. System.Text.StringBuilder sb = new System.Text.StringBuilder ();
  523. bool fSpace = false;
  524. for (int i = 0; i < str.Length; i++) {
  525. char ch = str [i];
  526. if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
  527. {
  528. fSpace = true;
  529. }
  530. else
  531. {
  532. if (fSpace)
  533. {
  534. fSpace = false;
  535. if (sb.Length > 0)
  536. sb.Append (' ');
  537. }
  538. sb.Append (ch);
  539. }
  540. }
  541. return sb.ToString ();
  542. }
  543. public override string ToString ()
  544. {
  545. return String.Concat (new string [] {
  546. "normalize-space(",
  547. arg0 != null ? arg0.ToString () : String.Empty,
  548. ")"});
  549. }
  550. }
  551. internal class XPathFunctionTranslate : XPathFunction
  552. {
  553. Expression arg0, arg1, arg2;
  554. public XPathFunctionTranslate (FunctionArguments args) : base (args)
  555. {
  556. if (args == null || args.Tail == null || args.Tail.Tail == null || args.Tail.Tail.Tail != null)
  557. throw new XPathException ("translate takes 3 args");
  558. arg0 = args.Arg;
  559. arg1 = args.Tail.Arg;
  560. arg2= args.Tail.Tail.Arg;
  561. }
  562. public override XPathResultType ReturnType { get { return XPathResultType.String; }}
  563. public override object Evaluate (BaseIterator iter)
  564. {
  565. string s0 = arg0.EvaluateString (iter);
  566. string s1 = arg1.EvaluateString (iter);
  567. string s2 = arg2.EvaluateString (iter);
  568. StringBuilder ret = new StringBuilder (s0.Length);
  569. int pos = 0, len = s0.Length, s2len = s2.Length;
  570. while (pos < len) {
  571. int idx = s1.IndexOf (s0 [pos]);
  572. if (idx != -1) {
  573. if (idx < s2len)
  574. ret.Append (s2 [idx]);
  575. }
  576. else
  577. ret.Append (s0 [pos]);
  578. pos++;
  579. }
  580. return ret.ToString ();
  581. }
  582. public override string ToString ()
  583. {
  584. return String.Concat (new string [] {
  585. "string-length(",
  586. arg0.ToString (), ",",
  587. arg1.ToString (), ",",
  588. arg2.ToString (), ")"});
  589. }
  590. }
  591. internal class XPathFunctionBoolean : XPathFunction
  592. {
  593. Expression arg0;
  594. public XPathFunctionBoolean (FunctionArguments args) : base (args)
  595. {
  596. if (args != null) {
  597. arg0 = args.Arg;
  598. if (args.Tail != null)
  599. throw new XPathException ("boolean takes 1 or zero args");
  600. }
  601. }
  602. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  603. public override object Evaluate (BaseIterator iter)
  604. {
  605. if (arg0 == null)
  606. return XPathFunctions.ToBoolean (iter.Current.Value);
  607. return arg0.EvaluateBoolean (iter);
  608. }
  609. public override string ToString ()
  610. {
  611. return String.Concat (new string [] {"boolean(", arg0.ToString (), ")"});
  612. }
  613. }
  614. internal class XPathFunctionNot : XPathFunction
  615. {
  616. Expression arg0;
  617. public XPathFunctionNot (FunctionArguments args) : base (args)
  618. {
  619. if (args == null || args.Tail != null)
  620. throw new XPathException ("not takes one arg");
  621. arg0 = args.Arg;
  622. }
  623. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  624. public override object Evaluate (BaseIterator iter)
  625. {
  626. return !arg0.EvaluateBoolean (iter);
  627. }
  628. public override string ToString ()
  629. {
  630. return String.Concat (new string [] {"not(", arg0.ToString (), ")"});
  631. }
  632. }
  633. internal class XPathFunctionTrue : XPathFunction
  634. {
  635. public XPathFunctionTrue (FunctionArguments args) : base (args)
  636. {
  637. if (args != null)
  638. throw new XPathException ("true takes 0 args");
  639. }
  640. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  641. public override object Evaluate (BaseIterator iter)
  642. {
  643. return true;
  644. }
  645. public override string ToString ()
  646. {
  647. return "true()";
  648. }
  649. }
  650. internal class XPathFunctionFalse : XPathFunction
  651. {
  652. public XPathFunctionFalse (FunctionArguments args) : base (args)
  653. {
  654. if (args != null)
  655. throw new XPathException ("false takes 0 args");
  656. }
  657. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  658. public override object Evaluate (BaseIterator iter)
  659. {
  660. return false;
  661. }
  662. public override string ToString ()
  663. {
  664. return "false()";
  665. }
  666. }
  667. internal class XPathFunctionLang : XPathFunction
  668. {
  669. Expression arg0;
  670. public XPathFunctionLang (FunctionArguments args) : base (args)
  671. {
  672. if (args == null || args.Tail != null)
  673. throw new XPathException ("lang takes one arg");
  674. arg0 = args.Arg;
  675. }
  676. public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
  677. public override object Evaluate (BaseIterator iter)
  678. {
  679. string lang = arg0.EvaluateString (iter).ToLower ();
  680. string actualLang = iter.Current.XmlLang.ToLower ();
  681. return lang == actualLang || lang == (actualLang.Split ('-')[0]);
  682. }
  683. public override string ToString ()
  684. {
  685. return String.Concat (new string [] {"lang(", arg0.ToString (), ")"});
  686. }
  687. }
  688. internal class XPathFunctionNumber : XPathFunction
  689. {
  690. Expression arg0;
  691. public XPathFunctionNumber (FunctionArguments args) : base (args)
  692. {
  693. if (args != null) {
  694. arg0 = args.Arg;
  695. if (args.Tail != null)
  696. throw new XPathException ("number takes 1 or zero args");
  697. }
  698. }
  699. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  700. public override object Evaluate (BaseIterator iter)
  701. {
  702. if (arg0 == null)
  703. return XPathFunctions.ToNumber (iter.Current.Value);
  704. return arg0.EvaluateNumber (iter);
  705. }
  706. public override string ToString ()
  707. {
  708. return String.Concat (new string [] {"number(", arg0.ToString (), ")"});
  709. }
  710. }
  711. internal class XPathFunctionSum : XPathFunction
  712. {
  713. Expression arg0;
  714. public XPathFunctionSum (FunctionArguments args) : base (args)
  715. {
  716. if (args == null || args.Tail != null)
  717. throw new XPathException ("sum takes one arg");
  718. arg0 = args.Arg;
  719. }
  720. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  721. public override object Evaluate (BaseIterator iter)
  722. {
  723. XPathNodeIterator itr = arg0.EvaluateNodeSet (iter);
  724. double sum = 0;
  725. while (itr.MoveNext ())
  726. sum += XPathFunctions.ToNumber (itr.Current.Value);
  727. return sum;
  728. }
  729. public override string ToString ()
  730. {
  731. return String.Concat (new string [] {"sum(", arg0.ToString (), ")"});
  732. }
  733. }
  734. internal class XPathFunctionFloor : XPathFunction
  735. {
  736. Expression arg0;
  737. public XPathFunctionFloor (FunctionArguments args) : base (args)
  738. {
  739. if (args == null || args.Tail != null)
  740. throw new XPathException ("floor takes one arg");
  741. arg0 = args.Arg;
  742. }
  743. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  744. public override object Evaluate (BaseIterator iter)
  745. {
  746. return Math.Floor (arg0.EvaluateNumber (iter));
  747. }
  748. public override string ToString ()
  749. {
  750. return String.Concat (new string [] {"floor(", arg0.ToString (), ")"});
  751. }
  752. }
  753. internal class XPathFunctionCeil : XPathFunction
  754. {
  755. Expression arg0;
  756. public XPathFunctionCeil (FunctionArguments args) : base (args)
  757. {
  758. if (args == null || args.Tail != null)
  759. throw new XPathException ("ceil takes one arg");
  760. arg0 = args.Arg;
  761. }
  762. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  763. public override object Evaluate (BaseIterator iter)
  764. {
  765. return Math.Ceiling (arg0.EvaluateNumber (iter));
  766. }
  767. public override string ToString ()
  768. {
  769. return String.Concat (new string [] {"ceil(", arg0.ToString (), ")"});
  770. }
  771. }
  772. internal class XPathFunctionRound : XPathFunction
  773. {
  774. Expression arg0;
  775. public XPathFunctionRound (FunctionArguments args) : base (args)
  776. {
  777. if (args == null || args.Tail != null)
  778. throw new XPathException ("round takes one arg");
  779. arg0 = args.Arg;
  780. }
  781. public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
  782. public override object Evaluate (BaseIterator iter)
  783. {
  784. double arg = arg0.EvaluateNumber (iter);
  785. if (arg < -0.5 || arg > 0)
  786. return Math.Floor (arg + 0.5);
  787. return Math.Round (arg);
  788. }
  789. public override string ToString ()
  790. {
  791. return String.Concat (new string [] {"round(", arg0.ToString (), ")"});
  792. }
  793. }
  794. }