2 // System.Xml.XPath.DefaultContext & support classes
5 // Piers Haken (piersh@friskit.com)
7 // (C) 2002 Piers Haken
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Globalization;
34 using System.Xml.XPath;
38 namespace System.Xml.XPath
40 internal class XPathFunctions
42 public static bool ToBoolean (object arg)
45 throw new ArgumentNullException ();
50 double dArg = (double) arg;
51 return (dArg != 0.0 && !double.IsNaN (dArg));
54 return ((string) arg).Length != 0;
55 if (arg is BaseIterator)
57 BaseIterator iter = (BaseIterator) arg;
58 return iter.MoveNext ();
60 if (arg is XPathNavigator)
62 return ToBoolean (((XPathNavigator) arg).SelectChildren (XPathNodeType.All));
64 throw new ArgumentException ();
67 public static bool ToBoolean (bool b)
72 public static bool ToBoolean (double d)
74 return d != 0.0 && d != double.NaN;
77 public static bool ToBoolean (string s)
79 return s != null && s.Length > 0;
82 public static bool ToBoolean (BaseIterator iter)
84 return iter != null && iter.MoveNext ();
87 public static string ToString (object arg)
90 throw new ArgumentNullException ();
94 return ((bool) arg) ? "true" : "false";
96 return ToString ((double) arg);
97 if (arg is BaseIterator)
99 BaseIterator iter = (BaseIterator) arg;
100 if (!iter.MoveNext ())
102 return iter.Current.Value;
104 if (arg is XPathNavigator)
106 return ((XPathNavigator) arg).Value;
108 throw new ArgumentException ();
111 public static string ToString (double d)
113 // See XPath 1.0 section 4.2
114 if (d == Double.NegativeInfinity)
116 if (d == Double.PositiveInfinity)
119 // Return string in roundtrip format (currently it
120 // rather breaks things, so we don't use it until
121 // System.Double gets fixed.)
123 return d.ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
125 return ((double) d).ToString (System.Globalization.NumberFormatInfo.InvariantInfo);
129 public static double ToNumber (object arg)
132 throw new ArgumentNullException ();
133 if (arg is BaseIterator || arg is XPathNavigator)
134 arg = ToString (arg); // follow on
136 string s = arg as string;
137 return ToNumber (s); // use explicit overload
142 return Convert.ToDouble ((bool) arg);
143 throw new ArgumentException ();
146 public static double ToNumber (string arg)
149 throw new ArgumentNullException ();
150 string s = arg.Trim (XmlChar.WhitespaceChars);
154 return XmlConvert.ToDouble (s);
155 } catch (System.OverflowException) {
157 } catch (System.FormatException) {
163 internal abstract class XPathFunction : Expression
165 public XPathFunction (FunctionArguments args) {}
169 internal class XPathFunctionLast : XPathFunction
171 public XPathFunctionLast (FunctionArguments args) : base (args)
174 throw new XPathException ("last takes 0 args");
177 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
179 internal override bool Peer {
183 public override object Evaluate (BaseIterator iter)
185 return (double) iter.Count;
188 public override string ToString ()
193 internal override bool IsPositional {
199 internal class XPathFunctionPosition : XPathFunction
201 public XPathFunctionPosition (FunctionArguments args) : base (args)
204 throw new XPathException ("position takes 0 args");
207 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
209 internal override bool Peer {
213 public override object Evaluate (BaseIterator iter)
215 return (double) iter.CurrentPosition;
218 public override string ToString ()
223 internal override bool IsPositional {
229 internal class XPathFunctionCount : XPathFunction
233 public XPathFunctionCount (FunctionArguments args) : base (args)
235 if (args == null || args.Tail != null)
236 throw new XPathException ("count takes 1 arg");
241 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
243 internal override bool Peer {
244 get { return arg0.Peer; }
247 public override object Evaluate (BaseIterator iter)
249 return (double) arg0.EvaluateNodeSet (iter).Count;
252 public override bool EvaluateBoolean (BaseIterator iter)
254 if (arg0.GetReturnType (iter) == XPathResultType.NodeSet)
255 return arg0.EvaluateBoolean (iter);
257 return arg0.EvaluateNodeSet (iter).MoveNext ();
260 public override string ToString ()
262 return "count(" + arg0.ToString () + ")";
267 internal class XPathFunctionId : XPathFunction
271 public XPathFunctionId (FunctionArguments args) : base (args)
273 if (args == null || args.Tail != null)
274 throw new XPathException ("id takes 1 arg");
279 public Expression Id { get { return arg0; } }
281 private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
282 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
284 internal override bool Peer {
285 get { return arg0.Peer; }
288 public override object Evaluate (BaseIterator iter)
291 object val = arg0.Evaluate (iter);
293 BaseIterator valItr = val as BaseIterator;
297 while (valItr.MoveNext ())
298 strArgs += valItr.Current.Value + " ";
301 strArgs = XPathFunctions.ToString (val);
303 XPathNavigator n = iter.Current.Clone ();
304 ArrayList rgNodes = new ArrayList ();
305 string [] ids = strArgs.Split (rgchWhitespace);
306 for (int i = 0; i < ids.Length; i++)
307 if (n.MoveToId (ids [i]))
308 rgNodes.Add (n.Clone ());
310 rgNodes.Sort (XPathNavigatorComparer.Instance);
311 return new ListIterator (iter, rgNodes);
314 public override string ToString ()
316 return "id(" + arg0.ToString () + ")";
320 internal class XPathFunctionLocalName : XPathFunction
324 public XPathFunctionLocalName (FunctionArguments args) : base (args)
328 if (args.Tail != null)
329 throw new XPathException ("local-name takes 1 or zero args");
333 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
335 internal override bool Peer {
336 get { return arg0 != null ? arg0.Peer : true; }
339 public override object Evaluate (BaseIterator iter)
342 return iter.Current.LocalName;
344 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
345 if (argNs == null || !argNs.MoveNext ())
347 return argNs.Current.LocalName;
350 public override string ToString ()
352 return "local-name(" + arg0.ToString () + ")";
357 internal class XPathFunctionNamespaceUri : XPathFunction
361 public XPathFunctionNamespaceUri (FunctionArguments args) : base (args)
365 if (args.Tail != null)
366 throw new XPathException ("namespace-uri takes 1 or zero args");
370 internal override bool Peer {
371 get { return arg0 != null ? arg0.Peer : true; }
374 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
376 public override object Evaluate (BaseIterator iter)
379 return iter.Current.NamespaceURI;
381 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
382 if (argNs == null || !argNs.MoveNext ())
384 return argNs.Current.NamespaceURI;
387 public override string ToString ()
389 return "namespace-uri(" + arg0.ToString () + ")";
394 internal class XPathFunctionName : XPathFunction
398 public XPathFunctionName (FunctionArguments args) : base (args)
402 if (args.Tail != null)
403 throw new XPathException ("name takes 1 or zero args");
407 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
409 internal override bool Peer {
410 get { return arg0 != null ? arg0.Peer : true; }
413 public override object Evaluate (BaseIterator iter)
416 return iter.Current.Name;
418 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
419 if (argNs == null || !argNs.MoveNext ())
421 return argNs.Current.Name;
424 public override string ToString ()
426 return String.Concat ("name(",
427 arg0 != null ? arg0.ToString () : String.Empty,
433 internal class XPathFunctionString : XPathFunction
437 public XPathFunctionString (FunctionArguments args) : base (args)
441 if (args.Tail != null)
442 throw new XPathException ("string takes 1 or zero args");
446 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
448 internal override bool Peer {
449 get { return arg0 != null ? arg0.Peer : true; }
452 public override object Evaluate (BaseIterator iter)
455 return iter.Current.Value;
456 return arg0.EvaluateString (iter);
459 public override string ToString ()
461 return "string(" + arg0.ToString () + ")";
466 internal class XPathFunctionConcat : XPathFunction
470 public XPathFunctionConcat (FunctionArguments args) : base (args)
472 if (args == null || args.Tail == null)
473 throw new XPathException ("concat takes 2 or more args");
475 args.ToArrayList (rgs = new ArrayList ());
478 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
480 internal override bool Peer {
482 for (int i = 0; i < rgs.Count; i++)
483 if (!((Expression) rgs [i]).Peer)
489 public override object Evaluate (BaseIterator iter)
491 StringBuilder sb = new StringBuilder ();
494 for (int i = 0; i < len; i++)
495 sb.Append (((Expression)rgs[i]).EvaluateString (iter));
497 return sb.ToString ();
500 public override string ToString ()
502 StringBuilder sb = new StringBuilder ();
503 sb.Append ("concat(");
504 for (int i = 0; i < rgs.Count - 1; i++) {
505 sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [i].ToString ());
508 sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [rgs.Count - 1].ToString ());
510 return sb.ToString ();
515 internal class XPathFunctionStartsWith : XPathFunction
517 Expression arg0, arg1;
519 public XPathFunctionStartsWith (FunctionArguments args) : base (args)
521 if (args == null || args.Tail == null || args.Tail.Tail != null)
522 throw new XPathException ("starts-with takes 2 args");
525 arg1 = args.Tail.Arg;
528 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
530 internal override bool Peer {
531 get { return arg0.Peer && arg1.Peer; }
534 public override object Evaluate (BaseIterator iter)
536 return arg0.EvaluateString (iter).StartsWith (arg1.EvaluateString (iter));
539 public override string ToString ()
541 return String.Concat ("starts-with(", arg0.ToString (), ",", arg1.ToString (), ")");
546 internal class XPathFunctionContains : XPathFunction
548 Expression arg0, arg1;
550 public XPathFunctionContains (FunctionArguments args) : base (args)
552 if (args == null || args.Tail == null || args.Tail.Tail != null)
553 throw new XPathException ("contains takes 2 args");
556 arg1 = args.Tail.Arg;
559 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
561 internal override bool Peer {
562 get { return arg0.Peer && arg1.Peer; }
565 public override object Evaluate (BaseIterator iter)
567 return arg0.EvaluateString (iter).IndexOf (arg1.EvaluateString (iter)) != -1;
570 public override string ToString ()
572 return String.Concat ("contains(", arg0.ToString (), ",", arg1.ToString (), ")");
577 internal class XPathFunctionSubstringBefore : XPathFunction
579 Expression arg0, arg1;
581 public XPathFunctionSubstringBefore (FunctionArguments args) : base (args)
583 if (args == null || args.Tail == null || args.Tail.Tail != null)
584 throw new XPathException ("substring-before takes 2 args");
587 arg1 = args.Tail.Arg;
590 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
592 internal override bool Peer {
593 get { return arg0.Peer && arg1.Peer; }
596 public override object Evaluate (BaseIterator iter)
598 string str1 = arg0.EvaluateString (iter);
599 string str2 = arg1.EvaluateString (iter);
600 int ich = str1.IndexOf (str2);
603 return str1.Substring (0, ich);
606 public override string ToString ()
608 return String.Concat ("substring-before(", arg0.ToString (), ",", arg1.ToString (), ")");
613 internal class XPathFunctionSubstringAfter : XPathFunction
615 Expression arg0, arg1;
617 public XPathFunctionSubstringAfter (FunctionArguments args) : base (args)
619 if (args == null || args.Tail == null || args.Tail.Tail != null)
620 throw new XPathException ("substring-after takes 2 args");
623 arg1 = args.Tail.Arg;
626 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
628 internal override bool Peer {
629 get { return arg0.Peer && arg1.Peer; }
632 public override object Evaluate (BaseIterator iter)
634 string str1 = arg0.EvaluateString (iter);
635 string str2 = arg1.EvaluateString (iter);
636 int ich = str1.IndexOf (str2);
639 return str1.Substring (ich + str2.Length);
642 public override string ToString ()
644 return String.Concat ("substring-after(", arg0.ToString (), ",", arg1.ToString (), ")");
649 internal class XPathFunctionSubstring : XPathFunction
651 Expression arg0, arg1, arg2;
653 public XPathFunctionSubstring (FunctionArguments args) : base (args)
655 if (args == null || args.Tail == null || (args.Tail.Tail != null && args.Tail.Tail.Tail != null))
656 throw new XPathException ("substring takes 2 or 3 args");
659 arg1 = args.Tail.Arg;
660 if (args.Tail.Tail != null)
661 arg2= args.Tail.Tail.Arg;
664 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
666 internal override bool Peer {
667 get { return arg0.Peer && arg1.Peer && (arg2 != null ? arg2.Peer : true); }
670 public override object Evaluate (BaseIterator iter)
672 string str = arg0.EvaluateString (iter);
673 double ich = Math.Round (arg1.EvaluateNumber (iter)) - 1;
674 if (Double.IsNaN (ich) ||
675 Double.IsNegativeInfinity (ich) ||
676 ich >= (double) str.Length)
683 return str.Substring ((int) ich);
687 double cch = Math.Round (arg2.EvaluateNumber (iter));
688 if (Double.IsNaN (cch))
690 if (ich < 0.0 || cch < 0.0)
697 double cchMax = (double) str.Length - ich;
700 return str.Substring ((int) ich, (int) cch);
704 public override string ToString ()
706 return String.Concat (new string [] {
707 "substring(", arg0.ToString (), ",", arg1.ToString (), ",", arg2.ToString (), ")"});
712 internal class XPathFunctionStringLength : XPathFunction
716 public XPathFunctionStringLength (FunctionArguments args) : base (args)
720 if (args.Tail != null)
721 throw new XPathException ("string-length takes 1 or zero args");
725 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
727 internal override bool Peer {
728 get { return arg0 != null ? arg0.Peer : true; }
731 public override object Evaluate (BaseIterator iter)
735 str = arg0.EvaluateString (iter);
737 str = iter.Current.Value;
738 return (double) str.Length;
741 public override string ToString ()
743 return String.Concat (new string [] {
744 "string-length(", arg0.ToString (), ")"});
749 internal class XPathFunctionNormalizeSpace : XPathFunction
753 public XPathFunctionNormalizeSpace (FunctionArguments args) : base (args)
757 if (args.Tail != null)
758 throw new XPathException ("normalize-space takes 1 or zero args");
762 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
764 internal override bool Peer {
765 get { return arg0 !=null ? arg0.Peer : true; }
768 public override object Evaluate (BaseIterator iter)
772 str = arg0.EvaluateString (iter);
774 str = iter.Current.Value;
775 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
777 for (int i = 0; i < str.Length; i++) {
779 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
794 return sb.ToString ();
797 public override string ToString ()
799 return String.Concat (new string [] {
801 arg0 != null ? arg0.ToString () : String.Empty,
807 internal class XPathFunctionTranslate : XPathFunction
809 Expression arg0, arg1, arg2;
811 public XPathFunctionTranslate (FunctionArguments args) : base (args)
813 if (args == null || args.Tail == null || args.Tail.Tail == null || args.Tail.Tail.Tail != null)
814 throw new XPathException ("translate takes 3 args");
817 arg1 = args.Tail.Arg;
818 arg2= args.Tail.Tail.Arg;
821 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
823 internal override bool Peer {
824 get { return arg0.Peer && arg1.Peer && arg2.Peer; }
827 public override object Evaluate (BaseIterator iter)
829 string s0 = arg0.EvaluateString (iter);
830 string s1 = arg1.EvaluateString (iter);
831 string s2 = arg2.EvaluateString (iter);
833 StringBuilder ret = new StringBuilder (s0.Length);
835 int pos = 0, len = s0.Length, s2len = s2.Length;
838 int idx = s1.IndexOf (s0 [pos]);
842 ret.Append (s2 [idx]);
845 ret.Append (s0 [pos]);
850 return ret.ToString ();
853 public override string ToString ()
855 return String.Concat (new string [] {
857 arg0.ToString (), ",",
858 arg1.ToString (), ",",
859 arg2.ToString (), ")"});
863 internal abstract class XPathBooleanFunction : XPathFunction
865 public XPathBooleanFunction (FunctionArguments args) : base (args)
869 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
871 public override object StaticValue {
872 get { return StaticValueAsBoolean; }
876 internal class XPathFunctionBoolean : XPathBooleanFunction
880 public XPathFunctionBoolean (FunctionArguments args) : base (args)
884 if (args.Tail != null)
885 throw new XPathException ("boolean takes 1 or zero args");
889 internal override bool Peer {
890 get { return arg0 != null ? arg0.Peer : true; }
893 public override object Evaluate (BaseIterator iter)
896 return XPathFunctions.ToBoolean (iter.Current.Value);
897 return arg0.EvaluateBoolean (iter);
900 public override string ToString ()
902 return String.Concat (new string [] {"boolean(", arg0.ToString (), ")"});
907 internal class XPathFunctionNot : XPathBooleanFunction
911 public XPathFunctionNot (FunctionArguments args) : base (args)
913 if (args == null || args.Tail != null)
914 throw new XPathException ("not takes one arg");
918 internal override bool Peer {
919 get { return arg0.Peer; }
922 public override object Evaluate (BaseIterator iter)
924 return !arg0.EvaluateBoolean (iter);
927 public override string ToString ()
929 return String.Concat (new string [] {"not(", arg0.ToString (), ")"});
934 internal class XPathFunctionTrue : XPathBooleanFunction
936 public XPathFunctionTrue (FunctionArguments args) : base (args)
939 throw new XPathException ("true takes 0 args");
942 public override bool HasStaticValue {
946 public override bool StaticValueAsBoolean {
950 internal override bool Peer {
954 public override object Evaluate (BaseIterator iter)
959 public override string ToString ()
966 internal class XPathFunctionFalse : XPathBooleanFunction
968 public XPathFunctionFalse (FunctionArguments args) : base (args)
971 throw new XPathException ("false takes 0 args");
974 public override bool HasStaticValue {
978 public override bool StaticValueAsBoolean {
979 get { return false; }
982 internal override bool Peer {
986 public override object Evaluate (BaseIterator iter)
991 public override string ToString ()
998 internal class XPathFunctionLang : XPathFunction
1002 public XPathFunctionLang (FunctionArguments args) : base (args)
1004 if (args == null || args.Tail != null)
1005 throw new XPathException ("lang takes one arg");
1009 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
1011 internal override bool Peer {
1012 get { return arg0.Peer; }
1015 public override object Evaluate (BaseIterator iter)
1017 return EvaluateBoolean (iter);
1020 public override bool EvaluateBoolean (BaseIterator iter)
1022 string lang = arg0.EvaluateString (iter).ToLower (CultureInfo.InvariantCulture);
1023 string actualLang = iter.Current.XmlLang.ToLower (CultureInfo.InvariantCulture);
1025 return lang == actualLang || lang == (actualLang.Split ('-')[0]);
1028 public override string ToString ()
1030 return String.Concat (new string [] {"lang(", arg0.ToString (), ")"});
1034 internal abstract class XPathNumericFunction : XPathFunction
1036 internal XPathNumericFunction (FunctionArguments args)
1041 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
1043 public override object StaticValue {
1044 get { return StaticValueAsNumber; }
1048 internal class XPathFunctionNumber : XPathNumericFunction
1052 public XPathFunctionNumber (FunctionArguments args) : base (args)
1056 if (args.Tail != null)
1057 throw new XPathException ("number takes 1 or zero args");
1061 public override Expression Optimize ()
1065 arg0 = arg0.Optimize ();
1066 return !arg0.HasStaticValue ?
1068 new ExprNumber (StaticValueAsNumber);
1071 public override bool HasStaticValue {
1072 get { return arg0 != null && arg0.HasStaticValue; }
1075 public override double StaticValueAsNumber {
1076 get { return arg0 != null ? arg0.StaticValueAsNumber : 0; }
1079 internal override bool Peer {
1080 get { return arg0 != null ? arg0.Peer : true; }
1083 public override object Evaluate (BaseIterator iter)
1086 return XPathFunctions.ToNumber (iter.Current.Value);
1087 return arg0.EvaluateNumber (iter);
1090 public override string ToString ()
1092 return String.Concat (new string [] {"number(", arg0.ToString (), ")"});
1097 internal class XPathFunctionSum : XPathNumericFunction
1101 public XPathFunctionSum (FunctionArguments args) : base (args)
1103 if (args == null || args.Tail != null)
1104 throw new XPathException ("sum takes one arg");
1108 internal override bool Peer {
1109 get { return arg0.Peer; }
1112 public override object Evaluate (BaseIterator iter)
1114 XPathNodeIterator itr = arg0.EvaluateNodeSet (iter);
1117 while (itr.MoveNext ())
1118 sum += XPathFunctions.ToNumber (itr.Current.Value);
1123 public override string ToString ()
1125 return String.Concat (new string [] {"sum(", arg0.ToString (), ")"});
1130 internal class XPathFunctionFloor : XPathNumericFunction
1134 public XPathFunctionFloor (FunctionArguments args) : base (args)
1136 if (args == null || args.Tail != null)
1137 throw new XPathException ("floor takes one arg");
1141 public override bool HasStaticValue {
1142 get { return arg0.HasStaticValue; }
1145 public override double StaticValueAsNumber {
1146 get { return HasStaticValue ? Math.Floor (arg0.StaticValueAsNumber) : 0; }
1149 internal override bool Peer {
1150 get { return arg0.Peer; }
1153 public override object Evaluate (BaseIterator iter)
1155 return Math.Floor (arg0.EvaluateNumber (iter));
1158 public override string ToString ()
1160 return String.Concat (new string [] {"floor(", arg0.ToString (), ")"});
1165 internal class XPathFunctionCeil : XPathNumericFunction
1169 public XPathFunctionCeil (FunctionArguments args) : base (args)
1171 if (args == null || args.Tail != null)
1172 throw new XPathException ("ceil takes one arg");
1176 public override bool HasStaticValue {
1177 get { return arg0.HasStaticValue; }
1180 public override double StaticValueAsNumber {
1181 get { return HasStaticValue ? Math.Ceiling (arg0.StaticValueAsNumber) : 0; }
1184 internal override bool Peer {
1185 get { return arg0.Peer; }
1188 public override object Evaluate (BaseIterator iter)
1190 return Math.Ceiling (arg0.EvaluateNumber (iter));
1193 public override string ToString ()
1195 return String.Concat (new string [] {"ceil(", arg0.ToString (), ")"});
1200 internal class XPathFunctionRound : XPathNumericFunction
1204 public XPathFunctionRound (FunctionArguments args) : base (args)
1206 if (args == null || args.Tail != null)
1207 throw new XPathException ("round takes one arg");
1211 public override bool HasStaticValue {
1212 get { return arg0.HasStaticValue; }
1215 public override double StaticValueAsNumber {
1216 get { return HasStaticValue ? Round (arg0.StaticValueAsNumber) : 0; }
1219 internal override bool Peer {
1220 get { return arg0.Peer; }
1223 public override object Evaluate (BaseIterator iter)
1225 return Round (arg0.EvaluateNumber (iter));
1228 private double Round (double arg)
1230 if (arg < -0.5 || arg > 0)
1231 return Math.Floor (arg + 0.5);
1232 return Math.Round (arg);
1235 public override string ToString ()
1237 return String.Concat (new string [] {"round(", arg0.ToString (), ")"});