2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl / XslFunctions.cs
1 //
2 // XsltCompiledContext.cs
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 // (C) 2003 Ben Maurer
8 // (C) 2004 Atsushi Enomoto
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.Collections;
33 using System.Globalization;
34 using System.Reflection;
35 using System.Text;
36 using System.Xml;
37 using System.Xml.XPath;
38 using System.Xml.Xsl;
39 using Mono.Xml.Xsl;
40
41 using QName = System.Xml.XmlQualifiedName;
42
43 namespace Mono.Xml.Xsl
44 {
45         internal abstract class XPFuncImpl : IXsltContextFunction 
46         {
47                 int minargs, maxargs;
48                 XPathResultType returnType;
49                 XPathResultType [] argTypes;
50
51                 public XPFuncImpl () {}
52                 public XPFuncImpl (int minArgs, int maxArgs, XPathResultType returnType, XPathResultType[] argTypes)
53                 {
54                         this.Init(minArgs, maxArgs, returnType, argTypes);
55                 }
56                 
57                 protected void Init (int minArgs, int maxArgs, XPathResultType returnType, XPathResultType[] argTypes)
58                 {
59                         this.minargs    = minArgs;
60                         this.maxargs    = maxArgs;
61                         this.returnType = returnType;
62                         this.argTypes   = argTypes;
63                 }
64
65                 public int Minargs { get { return this.minargs; }}
66                 public int Maxargs { get { return this.maxargs; }}
67                 public XPathResultType ReturnType { get { return this.returnType; }}
68                 public XPathResultType [] ArgTypes { get { return this.argTypes; }}
69                 public object Invoke (XsltContext xsltContext, object [] args, XPathNavigator docContext)
70                 {
71                         return Invoke ((XsltCompiledContext)xsltContext, args, docContext);
72                 }
73                 
74                 public abstract object Invoke (XsltCompiledContext xsltContext, object [] args, XPathNavigator docContext);
75                 
76                 public static XPathResultType GetXPathType (Type type, XPathNavigator node) {
77                         switch (Type.GetTypeCode(type)) {
78                         case TypeCode.String:
79                                 return XPathResultType.String;
80                         case TypeCode.Boolean:
81                                 return XPathResultType.Boolean;
82                         case TypeCode.Object:
83                                 if (typeof (XPathNavigator).IsAssignableFrom (type) || typeof (IXPathNavigable).IsAssignableFrom (type))
84                                         return XPathResultType.Navigator;
85                                 
86                                 if (typeof (XPathNodeIterator).IsAssignableFrom (type))
87                                         return XPathResultType.NodeSet;
88                                 
89                                 return XPathResultType.Any;
90                         case TypeCode.DateTime :
91                                 throw new XsltException ("Invalid type DateTime was specified.", null, node);
92                         default: // Numeric
93                                 return XPathResultType.Number;
94                         } 
95                 }
96         }
97         
98         class XsltExtensionFunction : XPFuncImpl 
99         {
100                 private object extension;
101                 private MethodInfo method;
102                 private TypeCode [] typeCodes;
103
104                 public XsltExtensionFunction (object extension, MethodInfo method, XPathNavigator currentNode)
105                 {
106                         this.extension = extension;
107                         this.method = method;
108
109                         ParameterInfo [] parameters = method.GetParameters ();
110                         int minArgs = parameters.Length;
111                         int maxArgs = parameters.Length;
112                         
113                         this.typeCodes = new TypeCode [parameters.Length];
114                         XPathResultType[] argTypes = new XPathResultType [parameters.Length];
115                         
116                         bool canBeOpt = true;
117                         for (int i = parameters.Length - 1; 0 <= i; i--) { // optionals at the end
118                                 typeCodes [i] = Type.GetTypeCode (parameters [i].ParameterType);
119                                 argTypes [i] = GetXPathType (parameters [i].ParameterType, currentNode);
120                                 if (canBeOpt) {
121                                         if (parameters[i].IsOptional)
122                                                 minArgs --;
123                                         else
124                                                 canBeOpt = false;
125                                 }
126                         }
127                         base.Init (minArgs, maxArgs, GetXPathType (method.ReturnType, currentNode), argTypes);
128                 }
129
130                 public override object Invoke (XsltCompiledContext xsltContext, object [] args, XPathNavigator docContext)
131                 {
132                         try {
133                                 ParameterInfo [] pis = method.GetParameters ();
134                                 object [] castedArgs = new object [pis.Length];
135                                 for (int i = 0; i < args.Length; i++) {
136                                         Type t = pis [i].ParameterType;
137                                         switch (t.FullName) {
138                                         case "System.Int16":
139                                         case "System.UInt16":
140                                         case "System.Int32":
141                                         case "System.UInt32":
142                                         case "System.Int64":
143                                         case "System.UInt64":
144                                         case "System.Single":
145                                         case "System.Decimal":
146                                                 castedArgs [i] = Convert.ChangeType (args [i], t);
147                                                 break;
148                                         default:
149                                                 castedArgs [i] = args [i];
150                                                 break;
151                                         }
152                                 }
153
154                                 object result = null;
155                                 switch (method.ReturnType.FullName) {
156                                 case "System.Int16":
157                                 case "System.UInt16":
158                                 case "System.Int32":
159                                 case "System.UInt32":
160                                 case "System.Int64":
161                                 case "System.UInt64":
162                                 case "System.Single":
163                                 case "System.Decimal":
164                                         result = (double) method.Invoke (extension, castedArgs);
165                                         break;
166                                 default:
167                                         result = method.Invoke(extension, castedArgs);
168                                         break;
169                                 }
170                                 IXPathNavigable navigable = result as IXPathNavigable;
171                                 if (navigable != null)
172                                         return navigable.CreateNavigator ();
173
174                                 return result;
175                         } catch (Exception ex) {
176                                 throw new XsltException ("Custom function reported an error.", ex);
177 //                              Debug.WriteLine ("****** INCORRECT RESOLUTION **********");
178                         }
179                 }
180         }
181         
182         class XsltCurrent : XPathFunction 
183         {
184                 public XsltCurrent (FunctionArguments args) : base (args)
185                 {
186                         if (args != null)
187                                 throw new XPathException ("current takes 0 args");
188                 }
189                 
190                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
191
192                 public override object Evaluate (BaseIterator iter)
193                 {
194                         return new SelfIterator ((iter.NamespaceManager as XsltCompiledContext).Processor.CurrentNode, null);
195                 }
196         }
197         
198         class XsltDocument : XPathFunction 
199         {
200                 Expression arg0, arg1;
201                 XPathNavigator doc;
202                 
203                 public XsltDocument (FunctionArguments args, Compiler c) : base (args)
204                 {
205                         if (args == null || (args.Tail != null && args.Tail.Tail != null))
206                                 throw new XPathException ("document takes one or two args");
207                         
208                         arg0 = args.Arg;
209                         if (args.Tail != null)
210                                 arg1 = args.Tail.Arg;
211                         doc = c.Input.Clone ();
212                 }
213                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
214                 
215                 public override object Evaluate (BaseIterator iter)
216                 {
217                         string baseUri = null;
218                         if (arg1 != null) {
219                                 XPathNodeIterator it = arg1.EvaluateNodeSet (iter);
220                                 if (it.MoveNext())
221                                         baseUri = it.Current.BaseURI;
222                                 else
223                                         baseUri = VoidBaseUriFlag;
224                         }
225
226                         object o = arg0.Evaluate (iter);
227                         if (o is XPathNodeIterator)
228                                 return GetDocument ((iter.NamespaceManager as XsltCompiledContext), (XPathNodeIterator)o, baseUri);
229                         else
230                                 return GetDocument ((iter.NamespaceManager as XsltCompiledContext), o is IFormattable ? ((IFormattable) o).ToString (null, CultureInfo.InvariantCulture) : o.ToString (), baseUri);
231                 }
232                 
233                 static string VoidBaseUriFlag = "&^)(*&%*^$&$VOID!BASE!URI!";
234                 
235                 Uri Resolve (string thisUri, string baseUri, XslTransformProcessor p)
236                 {
237 //                      Debug.WriteLine ("THIS: " + thisUri);
238 //                      Debug.WriteLine ("BASE: " + baseUri);
239                         XmlResolver r = p.Resolver;
240                         if (r == null)
241                                 return null;
242                         Uri uriBase = null;
243                         if (! object.ReferenceEquals (baseUri, VoidBaseUriFlag) && baseUri != String.Empty)
244                                 uriBase = r.ResolveUri (null, baseUri);
245                                 
246                         return r.ResolveUri (uriBase, thisUri);
247                 }
248                 
249                 XPathNodeIterator GetDocument (XsltCompiledContext xsltContext, XPathNodeIterator itr, string baseUri)
250                 {
251                         ArrayList list = new ArrayList ();
252                         Hashtable got = new Hashtable ();
253                         
254                         while (itr.MoveNext()) {
255                                 Uri uri = Resolve (itr.Current.Value, baseUri != null ? baseUri : /*itr.Current.BaseURI*/doc.BaseURI, xsltContext.Processor);
256                                 if (!got.ContainsKey (uri)) {
257                                         got.Add (uri, null);
258                                         if (uri != null && uri.ToString () == "") {
259                                                 XPathNavigator n = doc.Clone ();
260                                                 n.MoveToRoot ();
261                                                 list.Add (n);
262                                         } else
263                                                 list.Add (xsltContext.Processor.GetDocument (uri));
264                                 }
265                         }
266                         
267                         return new ListIterator (list, xsltContext, false);
268                 }
269         
270                 XPathNodeIterator GetDocument (XsltCompiledContext xsltContext, string arg0, string baseUri)
271                 {
272                         Uri uri = Resolve (arg0, baseUri != null ? baseUri : doc.BaseURI, xsltContext.Processor);
273                         XPathNavigator n;
274                         if (uri != null && uri.ToString () == "") {
275                                 n = doc.Clone ();
276                                 n.MoveToRoot ();
277                         } else
278                                 n = xsltContext.Processor.GetDocument (uri);
279                         
280                         return new SelfIterator (n, xsltContext);
281                 }
282         }
283         
284         class XsltElementAvailable : XPathFunction 
285         {
286                 Expression arg0;
287                 XmlNamespaceManager nsm;
288                 
289                 public XsltElementAvailable (FunctionArguments args, IStaticXsltContext ctx) : base (args)
290                 {
291                         if (args == null || args.Tail != null)
292                                 throw new XPathException ("element-available takes 1 arg");
293                         
294                         arg0 = args.Arg;
295                         nsm = ctx.GetNsm ();
296                 }
297                 
298                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
299
300                 public override object Evaluate (BaseIterator iter)
301                 {
302                         QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), nsm);
303
304                         return (
305                                 (name.Namespace == Compiler.XsltNamespace) &&
306                                 (
307                                         //
308                                         // A list of all the instructions (does not include top-level-elements)
309                                         //
310                                         name.Name == "apply-imports" ||
311                                         name.Name == "apply-templates" ||
312                                         name.Name == "call-template" ||
313                                         name.Name == "choose" ||
314                                         name.Name == "comment" ||
315                                         name.Name == "copy" ||
316                                         name.Name == "copy-of" ||
317                                         name.Name == "element" ||
318                                         name.Name == "fallback" ||
319                                         name.Name == "for-each" ||
320                                         name.Name == "message" ||
321                                         name.Name == "number" ||
322                                         name.Name == "processing-instruction" ||
323                                         name.Name == "text" ||
324                                         name.Name == "value-of" ||
325                                         name.Name == "variable"
326                                 )
327                         );
328                 }
329         }
330
331         class XsltFormatNumber : XPathFunction 
332         {
333                 Expression arg0, arg1, arg2;
334                 XmlNamespaceManager nsm;
335                 
336                 public XsltFormatNumber (FunctionArguments args, IStaticXsltContext ctx) : base (args)
337                 {
338                         if (args == null || args.Tail == null || (args.Tail.Tail != null && args.Tail.Tail.Tail != null))
339                                 throw new XPathException ("format-number takes 2 or 3 args");
340                         
341                         arg0 = args.Arg;
342                         arg1 = args.Tail.Arg;
343                         if (args.Tail.Tail != null) {
344                                 arg2= args.Tail.Tail.Arg;
345                                 nsm = ctx.GetNsm ();
346                         }
347                 }
348                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
349                 
350                 public override object Evaluate (BaseIterator iter)
351                 {
352                         double d = arg0.EvaluateNumber (iter);
353                         string s = arg1.EvaluateString (iter);
354                         QName nm = QName.Empty;
355                         
356                         if (arg2 != null)
357                                 nm = XslNameUtil.FromString (arg2.EvaluateString (iter), nsm);
358                         
359                         try {
360                                 return (iter.NamespaceManager as XsltCompiledContext).Processor.CompiledStyle
361                                 .LookupDecimalFormat (nm).FormatNumber (d, s);
362                         } catch (ArgumentException ex) {
363                                 throw new XsltException (ex.Message, ex, iter.Current);
364                         }
365                 }
366         }
367         
368         class XsltFunctionAvailable : XPathFunction 
369         {
370                 Expression arg0;
371                 XmlNamespaceManager nsm;
372                 
373                 public XsltFunctionAvailable (FunctionArguments args, IStaticXsltContext ctx) : base (args)
374                 {
375                         if (args == null || args.Tail != null)
376                                 throw new XPathException ("element-available takes 1 arg");
377                         
378                         arg0 = args.Arg;
379                         nsm = ctx.GetNsm ();
380                 }
381                 
382                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
383                 
384                 public override object Evaluate (BaseIterator iter)
385                 {
386                         
387                         string name = arg0.EvaluateString (iter);
388                         int colon = name.IndexOf (':');
389                         // extension function
390                         if (colon > 0)
391                                 return (iter.NamespaceManager as XsltCompiledContext).ResolveFunction (
392                                         XslNameUtil.FromString (name, nsm),
393                                         null) != null;
394                         
395                         return (
396                                 //
397                                 // XPath
398                                 //
399                                 name == "boolean" ||
400                                 name == "ceiling" ||
401                                 name == "concat" ||
402                                 name == "contains" ||
403                                 name == "count" ||
404                                 name == "false" ||
405                                 name == "floor" ||
406                                 name == "id"||
407                                 name == "lang" ||
408                                 name == "last" ||
409                                 name == "local-name" ||
410                                 name == "name" ||
411                                 name == "namespace-uri" ||
412                                 name == "normalize-space" ||
413                                 name == "not" ||
414                                 name == "number" ||
415                                 name == "position" ||
416                                 name == "round" ||
417                                 name == "starts-with" ||
418                                 name == "string" ||
419                                 name == "string-length" ||
420                                 name == "substring" ||
421                                 name == "substring-after" ||
422                                 name == "substring-before" ||
423                                 name == "sum" ||
424                                 name == "translate" ||
425                                 name == "true" ||
426                                 // XSLT
427                                 name == "document" ||
428                                 name == "format-number" ||
429                                 name == "function-available" ||
430                                 name == "generate-id" ||
431                                 name == "key" ||
432                                 name == "current" ||
433                                 name == "unparsed-entity-uri" ||
434                                 name == "element-available" ||
435                                 name == "system-property"
436                         );
437                 }
438         } 
439
440         class XsltGenerateId : XPathFunction 
441         {
442                 Expression arg0;
443                 public XsltGenerateId (FunctionArguments args) : base (args)
444                 {
445                         if (args != null) {
446                                 if (args.Tail != null)
447                                         throw new XPathException ("generate-id takes 1 or no args");
448                                 arg0 = args.Arg;
449                         }
450                 }
451                 
452                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
453                 public override object Evaluate (BaseIterator iter)
454                 {
455                         XPathNavigator n;
456                         if (arg0 != null) {
457                                 XPathNodeIterator itr = arg0.EvaluateNodeSet (iter);
458                                 if (itr.MoveNext ())
459                                         n = itr.Current.Clone ();
460                                 else
461                                         return string.Empty; // empty nodeset == empty string
462                         } else
463                                 n = iter.Current.Clone ();
464                         
465                         StringBuilder sb = new StringBuilder ("Mono"); // Ensure begins with alpha
466                         sb.Append (XmlConvert.EncodeLocalName (n.BaseURI));
467                         sb.Replace ('_', 'm'); // remove underscores from EncodeLocalName
468                         sb.Append (n.NodeType);
469                         sb.Append ('m');
470
471                         do {
472                                 sb.Append (IndexInParent (n));
473                                 sb.Append ('m');
474                         } while (n.MoveToParent ());
475                         
476                         return sb.ToString ();
477                 }
478                 
479                 int IndexInParent (XPathNavigator nav)
480                 {
481                         int n = 0;
482                         while (nav.MoveToPrevious ())
483                                 n++;
484                         
485                         return n;
486                 }
487         } 
488         
489         class XsltKey : XPathFunction 
490         {
491                 Expression arg0, arg1;
492                 XmlNamespaceManager nsm;
493                 XslKey key;
494                 
495                 public XsltKey (FunctionArguments args, IStaticXsltContext ctx) : base (args)
496                 {
497                         if (args == null || args.Tail == null)
498                                 throw new XPathException ("key takes 2 args");
499                         arg0 = args.Arg;
500                         arg1 = args.Tail.Arg;
501                         nsm = ctx.GetNsm ();
502                 }
503                 public Expression KeyName { get { return arg0; } }
504                 public Expression Field { get { return arg1; } }
505                 public XmlNamespaceManager NamespaceManager { get { return nsm; } }
506                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
507                 
508                 public override object Evaluate (BaseIterator iter)
509                 {
510                         QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), nsm);
511                         XsltCompiledContext ctx = iter.NamespaceManager as XsltCompiledContext;
512                         if (key == null)
513                                 key = ctx.Processor.CompiledStyle.Style.FindKey (name);
514
515                         ArrayList result = new ArrayList ();
516                         object o = arg1.Evaluate (iter);
517                         XPathNodeIterator it = o as XPathNodeIterator;
518                         
519                         if (it != null) {
520                                 while (it.MoveNext())
521                                         FindKeyMatch (ctx, it.Current.Value, result, iter.Current);
522                         } else {
523                                 FindKeyMatch (ctx, XPathFunctions.ToString (o), result, iter.Current);
524                         }
525                         
526                         return new ListIterator (result, (iter.NamespaceManager as XsltCompiledContext), true);
527                 }
528                 
529                 void FindKeyMatch (XsltCompiledContext xsltContext, string value, ArrayList result, XPathNavigator context)
530                 {
531                         XPathNavigator searchDoc = context.Clone ();
532                         searchDoc.MoveToRoot ();
533                         if (key != null) {
534                                 XPathNodeIterator desc = searchDoc.SelectDescendants (XPathNodeType.All, true);
535
536                                 while (desc.MoveNext ()) {
537                                         if (key.Matches (desc.Current, xsltContext, value))
538                                                 AddResult (result, desc.Current);
539                                         
540                                         if (desc.Current.MoveToFirstAttribute ()) {
541                                                 do {
542                                                         if (key.Matches (desc.Current, xsltContext, value))
543                                                                 AddResult (result, desc.Current);       
544                                                 } while (desc.Current.MoveToNextAttribute ());
545                                                 
546                                                 desc.Current.MoveToParent ();
547                                         }
548                                 }
549                         }
550                 }
551
552                 void AddResult (ArrayList result, XPathNavigator nav)
553                 {
554                         for (int i = 0; i < result.Count; i++) {
555                                 XmlNodeOrder docOrder = nav.ComparePosition (((XPathNavigator)result [i]));
556                                 if (docOrder == XmlNodeOrder.Same)
557                                         return;
558                                 
559                                 if (docOrder == XmlNodeOrder.Before) {
560                                         result.Insert(i, nav.Clone ());
561                                         return;
562                                 }
563                         }
564                         result.Add (nav.Clone ());
565                 }
566         }
567         
568         class XsltSystemProperty : XPathFunction 
569         {
570                 Expression arg0;
571                 XmlNamespaceManager nsm;
572                 
573                 public XsltSystemProperty (FunctionArguments args, IStaticXsltContext ctx) : base (args)
574                 {
575                         if (args == null || args.Tail != null)
576                                 throw new XPathException ("system-property takes 1 arg");
577                         
578                         arg0 = args.Arg;
579                         nsm = ctx.GetNsm ();
580                 }
581                 
582                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
583                 public override object Evaluate (BaseIterator iter)
584                 {
585                         QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), nsm);
586                         
587                         if (name.Namespace == Compiler.XsltNamespace) {
588                                 switch (name.Name) {
589                                         case "version": return "1.0";
590                                         case "vendor": return "Mono";
591                                         case "vendor-url": return "http://www.go-mono.com/";
592                                 }
593                         }
594                         
595                         return "";
596                 }
597         } 
598
599         class XsltUnparsedEntityUri : XPathFunction 
600         {
601                 Expression arg0;
602                 
603                 public XsltUnparsedEntityUri (FunctionArguments args) : base (args)
604                 {
605                         if (args == null || args.Tail != null)
606                                 throw new XPathException ("unparsed-entity-uri takes 1 arg");
607                         
608                         arg0 = args.Arg;
609                 }
610                 
611                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
612                 public override object Evaluate (BaseIterator iter)
613                 {
614                         IHasXmlNode xn = iter.Current as IHasXmlNode;
615                         if (xn == null)
616                                 return String.Empty;
617                         XmlNode n = xn.GetNode ();
618                         XmlDocumentType doctype = n.OwnerDocument.DocumentType;
619                         if (doctype == null)
620                                 return String.Empty;
621                         XmlEntity ent = doctype.Entities.GetNamedItem (arg0.EvaluateString (iter)) as XmlEntity;
622                         if (ent == null)
623                                 return String.Empty;
624                         else
625                                 return ent.BaseURI;
626                 }
627         }
628
629         class MSXslNodeSet : XPathFunction
630         {
631                 Expression arg0;
632
633                 public MSXslNodeSet (FunctionArguments args) : base (args)
634                 {
635                         if (args == null || args.Tail != null)
636                                 throw new XPathException ("element-available takes 1 arg");
637                         
638                         arg0 = args.Arg;
639                 }
640 \r
641                 public override XPathResultType ReturnType {\r
642                         get {\r
643                                 return XPathResultType.NodeSet;\r
644                         }\r
645                 }\r
646
647                 public override object Evaluate (BaseIterator iter)\r
648                 {\r
649                         XsltCompiledContext ctx = iter.NamespaceManager as XsltCompiledContext;\r
650                         XPathNavigator loc = iter.Current != null ? iter.Current.Clone () : null;\r
651                         XPathNavigator nav = arg0.EvaluateAs (iter, XPathResultType.Navigator) as XPathNavigator;\r
652                         if (nav == null) {\r
653                                 if (loc != null)\r
654                                         return new XsltException ("Cannot convert the XPath argument to a result tree fragment.", null, loc);\r
655                                 else\r
656                                         return new XsltException ("Cannot convert the XPath argument to a result tree fragment.", null);\r
657                         }\r
658                         ArrayList al = new ArrayList ();\r
659                         al.Add (nav);\r
660                         return new ListIterator (al, ctx, false);\r
661                 }
662         }
663 }