Merge pull request #961 from ermshiperete/bug-xamarin-18118
authorAlexis Christoforides <alexis@thenull.net>
Mon, 28 Apr 2014 18:16:46 +0000 (14:16 -0400)
committerAlexis Christoforides <alexis@thenull.net>
Mon, 28 Apr 2014 18:16:46 +0000 (14:16 -0400)
[System.XML] XSL bugfixes for #18118 #18114 #18113

mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslValueOf.cs
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs
mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs
mcs/class/System.XML/Mono.Xml.Xsl/XslFunctions.cs
mcs/class/System.XML/System.Xml.Xsl/XslCompiledTransform.cs
mcs/class/System.XML/System.Xml.Xsl/XslTransform.cs
mcs/class/System.XML/System.Xml_test.dll.sources
mcs/class/System.XML/Test/System.Xml.Xsl/XslCompiledTransformTests.cs [new file with mode: 0644]

index 0d2209bc54b9a59f2daf4940ef4aef15b7019c2a..80691bbc20f157194c5637d646b3530d25184247 100644 (file)
@@ -66,6 +66,7 @@ namespace Mono.Xml.Xsl.Operations {
                                                throw new XsltCompileException ("XSLT value-of element cannot contain any child.", null, c.Input);
                                        }
                                } while (c.Input.MoveToNext ());
+                               c.Input.MoveToParent ();
                        }
                }
                
index 430244ff882e7c595ae88949de6fb19099be5f2b..ec99c09c74d89d17d03e43cfdcacd88d55ac49dd 100644 (file)
@@ -171,7 +171,10 @@ namespace Mono.Xml.Xsl.Operations {
                
                protected override object GetValue (XslTransformProcessor p)
                {
+                       p.PushNodeset (new SelfIterator (p.Root, p.XPathContext));
+                       p.NodesetMoveNext ();
                        Evaluate (p);
+                       p.PopNodeset ();
                        return p.globalVariableTable [this];
                }
                        
index 5efdaea300f0c4a515cd30ccdf63fe2309b6ec57..e73889f23542f4df5383da76cd69c4721fba27e6 100644 (file)
@@ -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;
index a45267757f14264f3df7c6f279d091bcf9c532e3..1b3fc98d87a2008169940656d1173f84747de127 100644 (file)
@@ -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);
index efe7a6cf2d76b4c9583643a040cb10453f8a5de3..fd1c854ee3bbff67eae5cff10bc0525d0de8bb48 100644 (file)
@@ -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
index a3c2c5a70d35f6c70dcc80709ed78f5cfc8cfdc8..8ccdff7e14c34eed239aaa23b2b8501d75b745d6 100644 (file)
@@ -286,7 +286,7 @@ namespace System.Xml.Xsl {
 \r
                public void Load (XPathNavigator stylesheet, XmlResolver resolver, Evidence evidence)\r
                {\r
-                       s = new Compiler (debugger).Compile (stylesheet, resolver, evidence);\r
+                       s = new Compiler (debugger, true).Compile (stylesheet, resolver, evidence);\r
                }\r
 \r
                public void Load (XmlReader stylesheet, XmlResolver resolver, Evidence evidence)\r
index bf25cf598911e0e75e376f15fee57539aea6c87d..3698613cca1808f37891676b2c277ba16dcb3128 100644 (file)
@@ -112,3 +112,4 @@ System.Xml.Xsl/XsltCompileExceptionTests.cs
 System.Xml.Xsl/XsltExceptionCas.cs
 System.Xml.Xsl/XsltExceptionTests.cs
 System.Xml.XPath/XPathExceptionCas.cs
+System.Xml.Xsl/XslCompiledTransformTests.cs
diff --git a/mcs/class/System.XML/Test/System.Xml.Xsl/XslCompiledTransformTests.cs b/mcs/class/System.XML/Test/System.Xml.Xsl/XslCompiledTransformTests.cs
new file mode 100644 (file)
index 0000000..284f213
--- /dev/null
@@ -0,0 +1,112 @@
+using NUnit.Framework;
+using System.IO;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace MonoTests.System.Xml.Xsl
+{
+       [TestFixture]
+       public class XslCompiledTransformTests
+       {
+               [Test]
+               public void GlobalVariableReferencesAnotherGlobalVariable ()
+               {
+                       string xsl = @"<xsl:stylesheet version='1.0'
+xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+<xsl:variable name='global2'><xsl:value-of select='root/@attr' /></xsl:variable>
+<xsl:variable name='global1'>
+       <xsl:for-each select='//foo'>
+               <xsl:if test='@attr = $global2'>
+                       <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
+               </xsl:if>
+       </xsl:for-each>
+</xsl:variable>
+<xsl:template match='/'>
+       <root>
+               <xsl:value-of select='$global1' />
+       </root>
+</xsl:template>
+</xsl:stylesheet>";
+                       StringWriter sw = new StringWriter ();
+                       XslCompiledTransform t = new XslCompiledTransform ();
+                       t.Load (new XPathDocument (new StringReader (xsl)));
+                       t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root attr='B'><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
+                       Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?><root>foo: B</root>", sw.ToString ());
+               }
+
+               [Test]
+               public void MSXslNodeSetAcceptsNodeSet ()
+               {
+                       string xsl = @"<xsl:stylesheet version='1.0'
+xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>
+<xsl:template match='/'>
+       <root>
+               <!-- msxsl:node-set() accepts a node set -->
+               <xsl:for-each select='msxsl:node-set(root/foo)'>
+                       <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
+               </xsl:for-each>
+       </root>
+</xsl:template>
+</xsl:stylesheet>";
+                       StringWriter sw = new StringWriter ();
+                       XslCompiledTransform t = new XslCompiledTransform ();
+                       t.Load (new XPathDocument (new StringReader (xsl)));
+                       // should transform without an exception
+                       t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
+               }
+
+               [Test]
+               public void MSXslNodeSetAcceptsEmptyString ()
+               {
+                       string xsl = @"<xsl:stylesheet version='1.0'
+xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>
+<xsl:template match='/'>
+       <root>
+               <!-- msxsl:node-set() accepts an empty string -->
+               <xsl:variable name='empty'></xsl:variable>
+               <xsl:for-each select='msxsl:node-set($empty)'>
+                       <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
+               </xsl:for-each>
+       </root>
+</xsl:template>
+</xsl:stylesheet>";
+                       StringWriter sw = new StringWriter ();
+                       XslCompiledTransform t = new XslCompiledTransform ();
+                       t.Load (new XPathDocument (new StringReader (xsl)));
+                       // should transform without an exception
+                       t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
+               }
+
+               [Test]
+               public void ValueOfElementWithInsignificantWhitespace ()
+               {
+                       string xsl = @"<?xml version='1.0' encoding='utf-8'?>
+<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+<xsl:template match='/'>
+       <root>
+               <bar>
+                       <xsl:if test='root/@attr'>
+                               <xsl:value-of select='root/@attr'>
+                               </xsl:value-of>
+                       </xsl:if>
+               </bar>
+               <baz>
+                       <xsl:for-each select='root/foo'>
+                               <xsl:if test='position() != 1'>
+                                       <xsl:text>,</xsl:text>
+                               </xsl:if>
+                               <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
+                       </xsl:for-each>
+               </baz>
+       </root>
+</xsl:template>
+</xsl:stylesheet>";
+                       StringWriter sw = new StringWriter ();
+                       XslCompiledTransform t = new XslCompiledTransform ();
+                       t.Load (new XmlTextReader(new StringReader(xsl)));
+                       t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root attr='D'><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
+                       Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?><root><bar>D</bar><baz>foo: A,foo: B,foo: C</baz></root>", sw.ToString ());
+               }
+       }
+}