2005-11-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl / XslFunctions.cs
old mode 100755 (executable)
new mode 100644 (file)
index e42ae51..cf061cc
@@ -262,35 +262,45 @@ namespace Mono.Xml.Xsl
                XPathNodeIterator GetDocument (XsltCompiledContext xsltContext, XPathNodeIterator itr, string baseUri)
                {
                        ArrayList list = new ArrayList ();
-                       Hashtable got = new Hashtable ();
+                       try {
+                               Hashtable got = new Hashtable ();
                        
-                       while (itr.MoveNext()) {
-                               Uri uri = Resolve (itr.Current.Value, baseUri != null ? baseUri : /*itr.Current.BaseURI*/doc.BaseURI, xsltContext.Processor);
-                               if (!got.ContainsKey (uri)) {
-                                       got.Add (uri, null);
-                                       if (uri != null && uri.ToString () == "") {
-                                               XPathNavigator n = doc.Clone ();
-                                               n.MoveToRoot ();
-                                               list.Add (n);
-                                       } else
-                                               list.Add (xsltContext.Processor.GetDocument (uri));
+                               while (itr.MoveNext()) {
+                                       Uri uri = Resolve (itr.Current.Value, baseUri != null ? baseUri : /*itr.Current.BaseURI*/doc.BaseURI, xsltContext.Processor);
+                                       if (!got.ContainsKey (uri)) {
+                                               got.Add (uri, null);
+                                               if (uri != null && uri.ToString () == "") {
+                                                       XPathNavigator n = doc.Clone ();
+                                                       n.MoveToRoot ();
+                                                       list.Add (n);
+                                               } else
+                                                       list.Add (xsltContext.Processor.GetDocument (uri));
+                                       }
                                }
+                       } catch (Exception) {
+                               // Error recovery.
+                               // See http://www.w3.org/TR/xslt#document and
+                               // bug #75663.
+                               list.Clear ();
                        }
-                       
-                       return new ListIterator (list, xsltContext, false);
+                       return new ListIterator (list, xsltContext);
                }
        
                XPathNodeIterator GetDocument (XsltCompiledContext xsltContext, string arg0, string baseUri)
                {
-                       Uri uri = Resolve (arg0, baseUri != null ? baseUri : doc.BaseURI, xsltContext.Processor);
-                       XPathNavigator n;
-                       if (uri != null && uri.ToString () == "") {
-                               n = doc.Clone ();
-                               n.MoveToRoot ();
-                       } else
-                               n = xsltContext.Processor.GetDocument (uri);
+                       try {
+                               Uri uri = Resolve (arg0, baseUri != null ? baseUri : doc.BaseURI, xsltContext.Processor);
+                               XPathNavigator n;
+                               if (uri != null && uri.ToString () == "") {
+                                       n = doc.Clone ();
+                                       n.MoveToRoot ();
+                               } else
+                                       n = xsltContext.Processor.GetDocument (uri);
                        
-                       return new SelfIterator (n, xsltContext);
+                               return new SelfIterator (n, xsltContext);
+                       } catch (Exception) {
+                               return new ListIterator (new ArrayList (), xsltContext);
+                       }
                }
 
                public override string ToString ()
@@ -529,16 +539,15 @@ namespace Mono.Xml.Xsl
        class XsltKey : XPathFunction 
        {
                Expression arg0, arg1;
-               IStaticXsltContext ctx;
-               XslKey key;
+               IStaticXsltContext staticContext;
                
                public XsltKey (FunctionArguments args, IStaticXsltContext ctx) : base (args)
                {
+                       staticContext = ctx;
                        if (args == null || args.Tail == null)
                                throw new XPathException ("key takes 2 args");
                        arg0 = args.Arg;
                        arg1 = args.Tail.Arg;
-                       this.ctx = ctx;
                }
                public Expression KeyName { get { return arg0; } }
                public Expression Field { get { return arg1; } }
@@ -547,64 +556,21 @@ namespace Mono.Xml.Xsl
                internal override bool Peer {
                        get { return arg0.Peer && arg1.Peer; }
                }
-               
-               public override object Evaluate (BaseIterator iter)
-               {
-                       QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), this.ctx);
-                       XsltCompiledContext ctx = iter.NamespaceManager as XsltCompiledContext;
-                       if (key == null)
-                               key = ctx.Processor.CompiledStyle.Style.FindKey (name);
 
-                       ArrayList result = new ArrayList ();
-                       object o = arg1.Evaluate (iter);
-                       XPathNodeIterator it = o as XPathNodeIterator;
-                       
-                       if (it != null) {
-                               while (it.MoveNext())
-                                       FindKeyMatch (ctx, it.Current.Value, result, iter.Current);
-                       } else {
-                               FindKeyMatch (ctx, XPathFunctions.ToString (o), result, iter.Current);
-                       }
-                       
-                       return new ListIterator (result, (iter.NamespaceManager as XsltCompiledContext), true);
-               }
-               
-               void FindKeyMatch (XsltCompiledContext xsltContext, string value, ArrayList result, XPathNavigator context)
-               {
-                       XPathNavigator searchDoc = context.Clone ();
-                       searchDoc.MoveToRoot ();
-                       if (key != null) {
-                               XPathNodeIterator desc = searchDoc.SelectDescendants (XPathNodeType.All, true);
-
-                               while (desc.MoveNext ()) {
-                                       if (key.Matches (desc.Current, xsltContext, value))
-                                               AddResult (result, desc.Current);
-                                       
-                                       if (desc.Current.MoveToFirstAttribute ()) {
-                                               do {
-                                                       if (key.Matches (desc.Current, xsltContext, value))
-                                                               AddResult (result, desc.Current);       
-                                               } while (desc.Current.MoveToNextAttribute ());
-                                               
-                                               desc.Current.MoveToParent ();
-                                       }
-                               }
-                       }
+               public bool PatternMatches (XPathNavigator nav, XsltContext nsmgr)
+               {
+                       XsltCompiledContext ctx = nsmgr as XsltCompiledContext;
+                       // for key pattern, it must contain literal value
+                       return ctx.MatchesKey (nav, staticContext,
+                               arg0.StaticValueAsString,
+                               arg1.StaticValueAsString);
                }
 
-               void AddResult (ArrayList result, XPathNavigator nav)
+               public override object Evaluate (BaseIterator iter)
                {
-                       for (int i = 0; i < result.Count; i++) {
-                               XmlNodeOrder docOrder = nav.ComparePosition (((XPathNavigator)result [i]));
-                               if (docOrder == XmlNodeOrder.Same)
-                                       return;
-                               
-                               if (docOrder == XmlNodeOrder.Before) {
-                                       result.Insert(i, nav.Clone ());
-                                       return;
-                               }
-                       }
-                       result.Add (nav.Clone ());
+                       XsltCompiledContext ctx = iter.NamespaceManager
+                               as XsltCompiledContext;
+                       return ctx.EvaluateKey (staticContext, iter, arg0, arg1);
                }
        }
        
@@ -715,7 +681,7 @@ namespace Mono.Xml.Xsl
                        }
                        ArrayList al = new ArrayList ();
                        al.Add (nav);
-                       return new ListIterator (al, ctx, false);
+                       return new ListIterator (al, ctx);
                }
        }
 }