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;
\r
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.)
122 // return ((double) d).ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
123 return ((double) d).ToString (System.Globalization.NumberFormatInfo.InvariantInfo);
126 public static double ToNumber (object arg)
129 throw new ArgumentNullException ();
130 if (arg is BaseIterator || arg is XPathNavigator)
131 arg = ToString (arg); // follow on
133 string s = arg as string;
134 return ToNumber (s); // use explicit overload
139 return Convert.ToDouble ((bool) arg);
140 throw new ArgumentException ();
143 public static double ToNumber (string arg)
146 throw new ArgumentNullException ();
147 string s = arg.Trim (XmlChar.WhitespaceChars);
151 return XmlConvert.ToDouble (s);
152 } catch (System.OverflowException) {
154 } catch (System.FormatException) {
160 internal abstract class XPathFunction : Expression
162 public XPathFunction (FunctionArguments args) {}
166 internal class XPathFunctionLast : XPathFunction
168 public XPathFunctionLast (FunctionArguments args) : base (args)
171 throw new XPathException ("last takes 0 args");
174 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
176 internal override bool Peer {
180 public override object Evaluate (BaseIterator iter)
182 return (double) iter.Count;
185 public override string ToString ()
190 internal override bool IsPositional {
196 internal class XPathFunctionPosition : XPathFunction
198 public XPathFunctionPosition (FunctionArguments args) : base (args)
201 throw new XPathException ("position takes 0 args");
204 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
206 internal override bool Peer {
210 public override object Evaluate (BaseIterator iter)
212 return (double) iter.CurrentPosition;
215 public override string ToString ()
220 internal override bool IsPositional {
226 internal class XPathFunctionCount : XPathFunction
230 public XPathFunctionCount (FunctionArguments args) : base (args)
232 if (args == null || args.Tail != null)
233 throw new XPathException ("count takes 1 arg");
238 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
240 internal override bool Peer {
241 get { return arg0.Peer; }
244 public override object Evaluate (BaseIterator iter)
246 return (double) arg0.EvaluateNodeSet (iter).Count;
249 public override bool EvaluateBoolean (BaseIterator iter)
251 if (arg0.GetReturnType (iter) == XPathResultType.NodeSet)
252 return arg0.EvaluateBoolean (iter);
254 return arg0.EvaluateNodeSet (iter).MoveNext ();
257 public override string ToString ()
259 return "count(" + arg0.ToString () + ")";
264 internal class XPathFunctionId : XPathFunction
268 public XPathFunctionId (FunctionArguments args) : base (args)
270 if (args == null || args.Tail != null)
271 throw new XPathException ("id takes 1 arg");
276 public Expression Id { get { return arg0; } }
278 private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
279 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
281 internal override bool Peer {
282 get { return arg0.Peer; }
285 public override object Evaluate (BaseIterator iter)
288 object val = arg0.Evaluate (iter);
290 BaseIterator valItr = val as BaseIterator;
294 while (valItr.MoveNext ())
295 strArgs += valItr.Current.Value + " ";
298 strArgs = XPathFunctions.ToString (val);
300 XPathNavigator n = iter.Current.Clone ();
301 ArrayList rgNodes = new ArrayList ();
302 string [] ids = strArgs.Split (rgchWhitespace);
303 for (int i = 0; i < ids.Length; i++)
304 if (n.MoveToId (ids [i]))
305 rgNodes.Add (n.Clone ());
307 rgNodes.Sort (XPathNavigatorComparer.Instance);
308 return new ListIterator (iter, rgNodes);
311 public override string ToString ()
313 return "id(" + arg0.ToString () + ")";
317 internal class XPathFunctionLocalName : XPathFunction
321 public XPathFunctionLocalName (FunctionArguments args) : base (args)
325 if (args.Tail != null)
326 throw new XPathException ("local-name takes 1 or zero args");
330 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
332 internal override bool Peer {
333 get { return arg0 != null ? arg0.Peer : true; }
336 public override object Evaluate (BaseIterator iter)
339 return iter.Current.LocalName;
341 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
342 if (argNs == null || !argNs.MoveNext ())
344 return argNs.Current.LocalName;
347 public override string ToString ()
349 return "local-name(" + arg0.ToString () + ")";
354 internal class XPathFunctionNamespaceUri : XPathFunction
358 public XPathFunctionNamespaceUri (FunctionArguments args) : base (args)
362 if (args.Tail != null)
363 throw new XPathException ("namespace-uri takes 1 or zero args");
367 internal override bool Peer {
368 get { return arg0 != null ? arg0.Peer : true; }
371 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
373 public override object Evaluate (BaseIterator iter)
376 return iter.Current.NamespaceURI;
378 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
379 if (argNs == null || !argNs.MoveNext ())
381 return argNs.Current.NamespaceURI;
384 public override string ToString ()
386 return "namespace-uri(" + arg0.ToString () + ")";
391 internal class XPathFunctionName : XPathFunction
395 public XPathFunctionName (FunctionArguments args) : base (args)
399 if (args.Tail != null)
400 throw new XPathException ("name takes 1 or zero args");
404 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
406 internal override bool Peer {
407 get { return arg0 != null ? arg0.Peer : true; }
410 public override object Evaluate (BaseIterator iter)
413 return iter.Current.Name;
415 BaseIterator argNs = arg0.EvaluateNodeSet (iter);
416 if (argNs == null || !argNs.MoveNext ())
418 return argNs.Current.Name;
421 public override string ToString ()
423 return String.Concat ("name(",
424 arg0 != null ? arg0.ToString () : String.Empty,
430 internal class XPathFunctionString : XPathFunction
434 public XPathFunctionString (FunctionArguments args) : base (args)
438 if (args.Tail != null)
439 throw new XPathException ("string takes 1 or zero args");
443 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
445 internal override bool Peer {
446 get { return arg0 != null ? arg0.Peer : true; }
449 public override object Evaluate (BaseIterator iter)
452 return iter.Current.Value;
453 return arg0.EvaluateString (iter);
456 public override string ToString ()
458 return "string(" + arg0.ToString () + ")";
463 internal class XPathFunctionConcat : XPathFunction
467 public XPathFunctionConcat (FunctionArguments args) : base (args)
469 if (args == null || args.Tail == null)
470 throw new XPathException ("concat takes 2 or more args");
472 args.ToArrayList (rgs = new ArrayList ());
475 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
477 internal override bool Peer {
479 for (int i = 0; i < rgs.Count; i++)
480 if (!((Expression) rgs [i]).Peer)
486 public override object Evaluate (BaseIterator iter)
488 StringBuilder sb = new StringBuilder ();
491 for (int i = 0; i < len; i++)
492 sb.Append (((Expression)rgs[i]).EvaluateString (iter));
494 return sb.ToString ();
497 public override string ToString ()
499 StringBuilder sb = new StringBuilder ();
500 sb.Append ("concat(");
501 for (int i = 0; i < rgs.Count - 1; i++) {
502 sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [i].ToString ());
505 sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [rgs.Count - 1].ToString ());
507 return sb.ToString ();
512 internal class XPathFunctionStartsWith : XPathFunction
514 Expression arg0, arg1;
516 public XPathFunctionStartsWith (FunctionArguments args) : base (args)
518 if (args == null || args.Tail == null || args.Tail.Tail != null)
519 throw new XPathException ("starts-with takes 2 args");
522 arg1 = args.Tail.Arg;
525 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
527 internal override bool Peer {
528 get { return arg0.Peer && arg1.Peer; }
531 public override object Evaluate (BaseIterator iter)
533 return arg0.EvaluateString (iter).StartsWith (arg1.EvaluateString (iter));
536 public override string ToString ()
538 return String.Concat ("starts-with(", arg0.ToString (), ",", arg1.ToString (), ")");
543 internal class XPathFunctionContains : XPathFunction
545 Expression arg0, arg1;
547 public XPathFunctionContains (FunctionArguments args) : base (args)
549 if (args == null || args.Tail == null || args.Tail.Tail != null)
550 throw new XPathException ("contains takes 2 args");
553 arg1 = args.Tail.Arg;
556 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
558 internal override bool Peer {
559 get { return arg0.Peer && arg1.Peer; }
562 public override object Evaluate (BaseIterator iter)
564 return arg0.EvaluateString (iter).IndexOf (arg1.EvaluateString (iter)) != -1;
567 public override string ToString ()
569 return String.Concat ("contains(", arg0.ToString (), ",", arg1.ToString (), ")");
574 internal class XPathFunctionSubstringBefore : XPathFunction
576 Expression arg0, arg1;
578 public XPathFunctionSubstringBefore (FunctionArguments args) : base (args)
580 if (args == null || args.Tail == null || args.Tail.Tail != null)
581 throw new XPathException ("substring-before takes 2 args");
584 arg1 = args.Tail.Arg;
587 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
589 internal override bool Peer {
590 get { return arg0.Peer && arg1.Peer; }
593 public override object Evaluate (BaseIterator iter)
595 string str1 = arg0.EvaluateString (iter);
596 string str2 = arg1.EvaluateString (iter);
597 int ich = str1.IndexOf (str2);
600 return str1.Substring (0, ich);
603 public override string ToString ()
605 return String.Concat ("substring-before(", arg0.ToString (), ",", arg1.ToString (), ")");
610 internal class XPathFunctionSubstringAfter : XPathFunction
612 Expression arg0, arg1;
614 public XPathFunctionSubstringAfter (FunctionArguments args) : base (args)
616 if (args == null || args.Tail == null || args.Tail.Tail != null)
617 throw new XPathException ("substring-after takes 2 args");
620 arg1 = args.Tail.Arg;
623 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
625 internal override bool Peer {
626 get { return arg0.Peer && arg1.Peer; }
629 public override object Evaluate (BaseIterator iter)
631 string str1 = arg0.EvaluateString (iter);
632 string str2 = arg1.EvaluateString (iter);
633 int ich = str1.IndexOf (str2);
636 return str1.Substring (ich + str2.Length);
639 public override string ToString ()
641 return String.Concat ("substring-after(", arg0.ToString (), ",", arg1.ToString (), ")");
646 internal class XPathFunctionSubstring : XPathFunction
648 Expression arg0, arg1, arg2;
650 public XPathFunctionSubstring (FunctionArguments args) : base (args)
652 if (args == null || args.Tail == null || (args.Tail.Tail != null && args.Tail.Tail.Tail != null))
653 throw new XPathException ("substring takes 2 or 3 args");
656 arg1 = args.Tail.Arg;
657 if (args.Tail.Tail != null)
658 arg2= args.Tail.Tail.Arg;
661 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
663 internal override bool Peer {
664 get { return arg0.Peer && arg1.Peer && (arg2 != null ? arg2.Peer : true); }
667 public override object Evaluate (BaseIterator iter)
669 string str = arg0.EvaluateString (iter);
670 double ich = Math.Round (arg1.EvaluateNumber (iter)) - 1;
671 if (Double.IsNaN (ich) ||
672 Double.IsNegativeInfinity (ich) ||
673 ich >= (double) str.Length)
680 return str.Substring ((int) ich);
684 double cch = Math.Round (arg2.EvaluateNumber (iter));
685 if (Double.IsNaN (cch))
687 if (ich < 0.0 || cch < 0.0)
694 double cchMax = (double) str.Length - ich;
697 return str.Substring ((int) ich, (int) cch);
701 public override string ToString ()
703 return String.Concat (new string [] {
704 "substring(", arg0.ToString (), ",", arg1.ToString (), ",", arg2.ToString (), ")"});
709 internal class XPathFunctionStringLength : XPathFunction
713 public XPathFunctionStringLength (FunctionArguments args) : base (args)
717 if (args.Tail != null)
718 throw new XPathException ("string-length takes 1 or zero args");
722 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
724 internal override bool Peer {
725 get { return arg0 != null ? arg0.Peer : true; }
728 public override object Evaluate (BaseIterator iter)
732 str = arg0.EvaluateString (iter);
734 str = iter.Current.Value;
735 return (double) str.Length;
738 public override string ToString ()
740 return String.Concat (new string [] {
741 "string-length(", arg0.ToString (), ")"});
746 internal class XPathFunctionNormalizeSpace : XPathFunction
750 public XPathFunctionNormalizeSpace (FunctionArguments args) : base (args)
754 if (args.Tail != null)
755 throw new XPathException ("normalize-space takes 1 or zero args");
759 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
761 internal override bool Peer {
762 get { return arg0 !=null ? arg0.Peer : true; }
765 public override object Evaluate (BaseIterator iter)
769 str = arg0.EvaluateString (iter);
771 str = iter.Current.Value;
772 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
774 for (int i = 0; i < str.Length; i++) {
776 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
791 return sb.ToString ();
794 public override string ToString ()
796 return String.Concat (new string [] {
798 arg0 != null ? arg0.ToString () : String.Empty,
804 internal class XPathFunctionTranslate : XPathFunction
806 Expression arg0, arg1, arg2;
808 public XPathFunctionTranslate (FunctionArguments args) : base (args)
810 if (args == null || args.Tail == null || args.Tail.Tail == null || args.Tail.Tail.Tail != null)
811 throw new XPathException ("translate takes 3 args");
814 arg1 = args.Tail.Arg;
815 arg2= args.Tail.Tail.Arg;
818 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
820 internal override bool Peer {
821 get { return arg0.Peer && arg1.Peer && arg2.Peer; }
824 public override object Evaluate (BaseIterator iter)
826 string s0 = arg0.EvaluateString (iter);
827 string s1 = arg1.EvaluateString (iter);
828 string s2 = arg2.EvaluateString (iter);
830 StringBuilder ret = new StringBuilder (s0.Length);
832 int pos = 0, len = s0.Length, s2len = s2.Length;
835 int idx = s1.IndexOf (s0 [pos]);
839 ret.Append (s2 [idx]);
842 ret.Append (s0 [pos]);
847 return ret.ToString ();
850 public override string ToString ()
852 return String.Concat (new string [] {
854 arg0.ToString (), ",",
855 arg1.ToString (), ",",
856 arg2.ToString (), ")"});
860 internal abstract class XPathBooleanFunction : XPathFunction
862 public XPathBooleanFunction (FunctionArguments args) : base (args)
866 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
868 public override object StaticValue {
869 get { return StaticValueAsBoolean; }
873 internal class XPathFunctionBoolean : XPathBooleanFunction
877 public XPathFunctionBoolean (FunctionArguments args) : base (args)
881 if (args.Tail != null)
882 throw new XPathException ("boolean takes 1 or zero args");
886 internal override bool Peer {
887 get { return arg0 != null ? arg0.Peer : true; }
890 public override object Evaluate (BaseIterator iter)
893 return XPathFunctions.ToBoolean (iter.Current.Value);
894 return arg0.EvaluateBoolean (iter);
897 public override string ToString ()
899 return String.Concat (new string [] {"boolean(", arg0.ToString (), ")"});
904 internal class XPathFunctionNot : XPathBooleanFunction
908 public XPathFunctionNot (FunctionArguments args) : base (args)
910 if (args == null || args.Tail != null)
911 throw new XPathException ("not takes one arg");
915 internal override bool Peer {
916 get { return arg0.Peer; }
919 public override object Evaluate (BaseIterator iter)
921 return !arg0.EvaluateBoolean (iter);
924 public override string ToString ()
926 return String.Concat (new string [] {"not(", arg0.ToString (), ")"});
931 internal class XPathFunctionTrue : XPathBooleanFunction
933 public XPathFunctionTrue (FunctionArguments args) : base (args)
936 throw new XPathException ("true takes 0 args");
939 public override bool HasStaticValue {
943 public override bool StaticValueAsBoolean {
947 internal override bool Peer {
951 public override object Evaluate (BaseIterator iter)
956 public override string ToString ()
963 internal class XPathFunctionFalse : XPathBooleanFunction
965 public XPathFunctionFalse (FunctionArguments args) : base (args)
968 throw new XPathException ("false takes 0 args");
971 public override bool HasStaticValue {
975 public override bool StaticValueAsBoolean {
976 get { return false; }
979 internal override bool Peer {
983 public override object Evaluate (BaseIterator iter)
988 public override string ToString ()
995 internal class XPathFunctionLang : XPathFunction
999 public XPathFunctionLang (FunctionArguments args) : base (args)
1001 if (args == null || args.Tail != null)
1002 throw new XPathException ("lang takes one arg");
1006 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
1008 internal override bool Peer {
1009 get { return arg0.Peer; }
1012 public override object Evaluate (BaseIterator iter)
1014 return EvaluateBoolean (iter);
1017 public override bool EvaluateBoolean (BaseIterator iter)
1019 string lang = arg0.EvaluateString (iter).ToLower (CultureInfo.InvariantCulture);
1020 string actualLang = iter.Current.XmlLang.ToLower (CultureInfo.InvariantCulture);
1022 return lang == actualLang || lang == (actualLang.Split ('-')[0]);
1025 public override string ToString ()
1027 return String.Concat (new string [] {"lang(", arg0.ToString (), ")"});
1031 internal abstract class XPathNumericFunction : XPathFunction
1033 internal XPathNumericFunction (FunctionArguments args)
1038 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
1040 public override object StaticValue {
1041 get { return StaticValueAsNumber; }
1045 internal class XPathFunctionNumber : XPathNumericFunction
1049 public XPathFunctionNumber (FunctionArguments args) : base (args)
1053 if (args.Tail != null)
1054 throw new XPathException ("number takes 1 or zero args");
1058 public override Expression Optimize ()
1062 arg0 = arg0.Optimize ();
1063 return !arg0.HasStaticValue ?
1065 new ExprNumber (StaticValueAsNumber);
1068 public override bool HasStaticValue {
1069 get { return arg0 != null && arg0.HasStaticValue; }
1072 public override double StaticValueAsNumber {
1073 get { return arg0 != null ? arg0.StaticValueAsNumber : 0; }
1076 internal override bool Peer {
1077 get { return arg0 != null ? arg0.Peer : true; }
1080 public override object Evaluate (BaseIterator iter)
1083 return XPathFunctions.ToNumber (iter.Current.Value);
1084 return arg0.EvaluateNumber (iter);
1087 public override string ToString ()
1089 return String.Concat (new string [] {"number(", arg0.ToString (), ")"});
1094 internal class XPathFunctionSum : XPathNumericFunction
1098 public XPathFunctionSum (FunctionArguments args) : base (args)
1100 if (args == null || args.Tail != null)
1101 throw new XPathException ("sum takes one arg");
1105 internal override bool Peer {
1106 get { return arg0.Peer; }
1109 public override object Evaluate (BaseIterator iter)
1111 XPathNodeIterator itr = arg0.EvaluateNodeSet (iter);
1114 while (itr.MoveNext ())
1115 sum += XPathFunctions.ToNumber (itr.Current.Value);
1120 public override string ToString ()
1122 return String.Concat (new string [] {"sum(", arg0.ToString (), ")"});
1127 internal class XPathFunctionFloor : XPathNumericFunction
1131 public XPathFunctionFloor (FunctionArguments args) : base (args)
1133 if (args == null || args.Tail != null)
1134 throw new XPathException ("floor takes one arg");
1138 public override bool HasStaticValue {
1139 get { return arg0.HasStaticValue; }
1142 public override double StaticValueAsNumber {
1143 get { return HasStaticValue ? Math.Floor (arg0.StaticValueAsNumber) : 0; }
1146 internal override bool Peer {
1147 get { return arg0.Peer; }
1150 public override object Evaluate (BaseIterator iter)
1152 return Math.Floor (arg0.EvaluateNumber (iter));
1155 public override string ToString ()
1157 return String.Concat (new string [] {"floor(", arg0.ToString (), ")"});
1162 internal class XPathFunctionCeil : XPathNumericFunction
1166 public XPathFunctionCeil (FunctionArguments args) : base (args)
1168 if (args == null || args.Tail != null)
1169 throw new XPathException ("ceil takes one arg");
1173 public override bool HasStaticValue {
1174 get { return arg0.HasStaticValue; }
1177 public override double StaticValueAsNumber {
1178 get { return HasStaticValue ? Math.Ceiling (arg0.StaticValueAsNumber) : 0; }
1181 internal override bool Peer {
1182 get { return arg0.Peer; }
1185 public override object Evaluate (BaseIterator iter)
1187 return Math.Ceiling (arg0.EvaluateNumber (iter));
1190 public override string ToString ()
1192 return String.Concat (new string [] {"ceil(", arg0.ToString (), ")"});
1197 internal class XPathFunctionRound : XPathNumericFunction
1201 public XPathFunctionRound (FunctionArguments args) : base (args)
1203 if (args == null || args.Tail != null)
1204 throw new XPathException ("round takes one arg");
1208 public override bool HasStaticValue {
1209 get { return arg0.HasStaticValue; }
1212 public override double StaticValueAsNumber {
1213 get { return HasStaticValue ? Round (arg0.StaticValueAsNumber) : 0; }
1216 internal override bool Peer {
1217 get { return arg0.Peer; }
1220 public override object Evaluate (BaseIterator iter)
1222 return Round (arg0.EvaluateNumber (iter));
1225 private double Round (double arg)
1227 if (arg < -0.5 || arg > 0)
1228 return Math.Floor (arg + 0.5);
1229 return Math.Round (arg);
1232 public override string ToString ()
1234 return String.Concat (new string [] {"round(", arg0.ToString (), ")"});