Browse Source

[System.XML] Fix XSL node-set bug (#18114)

XSL node-set function now behaves more like MS version.
Damien Daspit 12 năm trước cách đây
mục cha
commit
ef1b6fb63c

+ 4 - 2
mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs

@@ -125,11 +125,13 @@ namespace Mono.Xml.Xsl
 		bool keyCompilationMode;	
 		string stylesheetVersion;
 		XsltDebuggerWrapper debugger;
+		bool strictMSXslNodeSet;
 
-		public Compiler (object debugger)
+		public Compiler (object debugger, bool strictMSXslNodeSet)
 		{
 			if (debugger != null)
 				this.debugger = new XsltDebuggerWrapper (debugger);
+			this.strictMSXslNodeSet = strictMSXslNodeSet;
 		}
 
 		public XsltDebuggerWrapper Debugger {
@@ -576,7 +578,7 @@ namespace Mono.Xml.Xsl
 		{
 			string ns = LookupNamespace (name.Namespace);
 			if (ns == XslStylesheet.MSXsltNamespace && name.Name == "node-set")
-				return new MSXslNodeSet (args);
+				return new MSXslNodeSet (strictMSXslNodeSet, args);
 			
 			if (ns != "")
 				return null;

+ 21 - 3
mcs/class/System.XML/Mono.Xml.Xsl/XslFunctions.cs

@@ -37,6 +37,7 @@ using System.Xml;
 using System.Xml.XPath;
 using System.Xml.Xsl;
 using Mono.Xml.Xsl;
+using Mono.Xml.XPath;
 
 using QName = System.Xml.XmlQualifiedName;
 
@@ -649,13 +650,15 @@ namespace Mono.Xml.Xsl
 
 	class MSXslNodeSet : XPathFunction
 	{
+		bool strict;
 		Expression arg0;
 
-		public MSXslNodeSet (FunctionArguments args) : base (args)
+		public MSXslNodeSet (bool strict, FunctionArguments args) : base (args)
 		{
 			if (args == null || args.Tail != null)
 				throw new XPathException ("element-available takes 1 arg");
-			
+
+			this.strict = strict;
 			arg0 = args.Arg;
 		}
 
@@ -673,13 +676,28 @@ namespace Mono.Xml.Xsl
 		{
 			XsltCompiledContext ctx = iter.NamespaceManager as XsltCompiledContext;
 			XPathNavigator loc = iter.Current != null ? iter.Current.Clone () : null;
-			XPathNavigator nav = arg0.EvaluateAs (iter, XPathResultType.Navigator) as XPathNavigator;
+			object val = arg0.Evaluate (iter);
+
+			XPathNavigator nav = val as XPathNavigator;
+			if (nav == null && !strict) {
+				var iterResult = val as XPathNodeIterator;
+				if (iterResult != null)
+					return iterResult;
+
+				var strResult = val as string;
+				if (strResult == string.Empty) {
+					DTMXPathDocumentWriter2 w = new DTMXPathDocumentWriter2 (ctx.Processor.Root.NameTable, 10);
+					nav = w.CreateDocument ().CreateNavigator ();
+				}
+			}
+
 			if (nav == null) {
 				if (loc != null)
 					return new XsltException ("Cannot convert the XPath argument to a result tree fragment.", null, loc);
 				else
 					return new XsltException ("Cannot convert the XPath argument to a result tree fragment.", null);
 			}
+
 			ArrayList al = new ArrayList ();
 			al.Add (nav);
 			return new ListIterator (al, ctx);

+ 1 - 1
mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform.cs

@@ -230,7 +230,7 @@ namespace System.Xml.Xsl
 		private void Load (XPathNavigator stylesheet,
 			XsltSettings settings, XmlResolver stylesheetResolver)
 		{
-			s = new Compiler (debugger).Compile (stylesheet, stylesheetResolver, null);
+			s = new Compiler (debugger, false).Compile (stylesheet, stylesheetResolver, null);
 		}
 
 		#endregion

+ 1 - 1
mcs/class/System.XML/System.Xml.Xsl/XslTransform.cs

@@ -286,7 +286,7 @@ namespace System.Xml.Xsl {
 
 		public void Load (XPathNavigator stylesheet, XmlResolver resolver, Evidence evidence)
 		{
-			s = new Compiler (debugger).Compile (stylesheet, resolver, evidence);
+			s = new Compiler (debugger, true).Compile (stylesheet, resolver, evidence);
 		}
 
 		public void Load (XmlReader stylesheet, XmlResolver resolver, Evidence evidence)