DefaultContext.cs 23 KB

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