DefaultContext.cs 23 KB

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