2 // System.Xml.Xsl.XslTransformTests.cs
5 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
7 // (C) 2002 Atsushi Enomoto
11 using System.Globalization;
15 using System.Xml.XPath;
17 using NUnit.Framework;
19 namespace MonoTests.System.Xml.Xsl
22 public class XslTransformTests : Assertion
29 public void GetReady()
31 doc = new XmlDocument ();
32 xslt = new XslTransform ();
33 result = new XmlDocument ();
37 public void TestBasicTransform ()
39 doc.LoadXml ("<root/>");
40 xslt.Load ("Test/XmlFiles/xsl/empty.xsl");
41 xslt.Transform ("Test/XmlFiles/xsl/empty.xsl", "Test/XmlFiles/xsl/result.xml");
42 result.Load ("Test/XmlFiles/xsl/result.xml");
43 AssertEquals ("count", 2, result.ChildNodes.Count);
47 [ExpectedException (typeof (XsltCompileException))]
48 public void InvalidStylesheet ()
50 XmlDocument doc = new XmlDocument ();
51 doc.LoadXml ("<xsl:element xmlns:xsl='http://www.w3.org/1999/XSL/Transform' />");
52 XslTransform t = new XslTransform ();
57 [ExpectedException (typeof (XsltCompileException))]
58 public void EmptyStylesheet ()
60 XmlDocument doc = new XmlDocument ();
61 XslTransform t = new XslTransform ();
66 [ExpectedException (typeof (XsltCompileException))]
67 public void InvalidStylesheet2 ()
69 string xml = @"<root>text</root>";
70 string xsl = @"<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
71 <xsl:template match='/root'>
72 <xsl:call-template name='foo'>
73 <xsl:with-param name='name' value='text()' />
76 <xsl:template name='foo'>
77 <xsl:param name='name' />
80 <xsl:variable name='last' value='text()' />
81 <xsl:value-of select='$last' />
87 XslTransform xslt = new XslTransform ();
88 xslt.Load (new XPathDocument (new XmlTextReader (xsl, XmlNodeType.Document, null)));
92 [Category ("NotWorking")] // it depends on "mcs" existence
93 public void MsxslTest() {
\r
94 string _styleSheet = @"
\r
95 <xslt:stylesheet xmlns:xslt=""http://www.w3.org/1999/XSL/Transform"" version=""1.0"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:stringutils=""urn:schemas-sourceforge.net-blah"">
\r
96 <xslt:output method=""text"" />
\r
97 <msxsl:script language=""C#"" implements-prefix=""stringutils"">
\r
99 string PadRight( string str, int padding) {
\r
100 return str.PadRight(padding);
\r
104 <xslt:template match=""test"">
\r
105 <xslt:value-of select=""stringutils:PadRight(@name, 20)"" />
\r
107 </xslt:stylesheet>";
\r
109 StringReader stringReader = new StringReader(_styleSheet);
\r
111 XslTransform transform = new XslTransform();
\r
112 XmlTextReader reader = new XmlTextReader(stringReader);
\r
113 transform.Load(reader, new XmlUrlResolver(), AppDomain.CurrentDomain.Evidence);
\r
115 StringBuilder sb = new StringBuilder();
\r
116 StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture);
\r
117 XsltArgumentList arguments = new XsltArgumentList();
\r
119 XmlDocument xmlDoc = new XmlDocument();
\r
120 xmlDoc.LoadXml("<test name=\"test\" />");
\r
122 // Do transformation
\r
123 transform.Transform(xmlDoc, new XsltArgumentList(), writer, new XmlUrlResolver());
\r
126 AssertEquals("test".PadRight(20), sb.ToString());
\r
130 public void MSXslNodeSet ()
132 string xsl = @"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>
133 <xsl:template match='/'>
135 <xsl:variable name='var'>
136 <xsl:copy-of select='root/foo' />
138 <xsl:for-each select='msxsl:node-set($var)/foo'>
139 <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
144 StringWriter sw = new StringWriter ();
145 XslTransform t = new XslTransform ();
146 t.Load (new XPathDocument (new StringReader (xsl)));
147 t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
148 AssertEquals (@"<?xml version=""1.0"" encoding=""utf-16""?><root xmlns:msxsl=""urn:schemas-microsoft-com:xslt"">foo: Afoo: Bfoo: C</root>", sw.ToString ());
152 [Category ("NotDotNet")]
\r
153 // Actually MS.NET here throws XsltException, but Mono returns
\r
154 // XPathException (since XPath evaluation engine generally
155 // catches (should catch) static error. It is implementation
\r
156 // dependent matter.
\r
157 [ExpectedException (typeof (XPathException))]
\r
158 public void MSXslNodeSetRejectsNodeSet ()
160 string xsl = @"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl='urn:schemas-microsoft-com:xslt'>
161 <xsl:template match='/'>
163 <!-- msxsl:node-set() does not accept a node set -->
164 <xsl:for-each select='msxsl:node-set(root/foo)'>
165 <xsl:value-of select='name(.)' />: <xsl:value-of select='@attr' />
170 StringWriter sw = new StringWriter ();
171 XslTransform t = new XslTransform ();
172 t.Load (new XPathDocument (new StringReader (xsl)));
173 t.Transform (new XPathDocument (new XmlTextReader (new StringReader ("<root><foo attr='A'/><foo attr='B'/><foo attr='C'/></root>"))), null, sw);
177 public void EvaluateEmptyVariableAsBoolean ()
179 string xsl = @"<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
180 <xsl:template match='/'>
181 <xsl:variable name='var'><empty /></xsl:variable>
182 <root><xsl:if test='$var'>true</xsl:if></root>
185 XslTransform t = new XslTransform ();
186 t.Load (new XPathDocument (new StringReader (xsl)));
187 StringWriter sw = new StringWriter ();
189 new XPathDocument (new StringReader ("<root/>")),
192 Assert (sw.ToString ().IndexOf ("true") > 0);
196 [ExpectedException (typeof (XsltCompileException))]
197 public void NotAllowedPatternAxis ()
199 string xsl = @"<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
200 <xsl:template match='/descendant-or-self::node()/elem'>
204 new XslTransform ().Load (new XPathDocument (
205 new StringReader (xsl)));
209 [ExpectedException (typeof (XsltCompileException))]
210 public void ImportIncorrectlyLocated ()
212 string xsl = @"<xsl:transform xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
213 <xsl:template match='/'></xsl:template>
214 <xsl:import href='dummy.xsl' />
216 new XslTransform ().Load (new XPathDocument (
217 new StringReader (xsl)));
220 private WeakReference StylesheetLoad (XslTransform t, string xsl)
222 XPathDocument doc = new XPathDocument (
223 new StringReader (xsl));
224 WeakReference wr = new WeakReference (doc);
229 private WeakReference StylesheetTransform (XslTransform t, string xml)
231 XPathDocument doc = new XPathDocument (
232 new StringReader (xml));
233 WeakReference wr = new WeakReference (doc);
234 t.Transform (doc, null, TextWriter.Null, null);
240 public void ErrorOnDocumentResolution ()
242 // XslTransform recovers from errors on document resolution.
243 string xslText = @"<xsl:stylesheet
244 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
246 <xsl:variable name='n'
247 select='document(""notexist.xml"")' />
248 <xsl:template match='/'>xx</xsl:template>
250 string xmlText = @"<root />";
251 XslTransform transform = new XslTransform ();
252 XPathDocument doc = new XPathDocument (
253 new XmlTextReader ("a.xsl", new StringReader (xslText)));
254 transform.Load (doc);
255 XPathDocument xmlDocument = new XPathDocument (new StringReader (xmlText));
256 transform.Transform (xmlDocument, null, TextWriter.Null);
261 public void LoadStyleFromNonRoot ()
263 XmlDocument doc = new XmlDocument ();
264 XslTransform xslt = new XslTransform ();
265 doc.LoadXml ("<root><dummy /><xsl:transform xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' /></root>");
266 XmlNode node = doc.ChildNodes [0].ChildNodes [1];
267 xslt.Load (node, null, null);
271 public void ReturnEmptyResultsAsXmlReader ()
274 XmlDocument doc = new XmlDocument ();
275 doc.LoadXml ("<xsl:transform xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' />");
276 XslTransform xslt = new XslTransform ();
277 xslt.Load (doc, null, null);
278 XmlReader reader = xslt.Transform(doc, null, new XmlUrlResolver ());
281 // another case - with xsl:output standalone='yes'
282 doc.LoadXml ("<xsl:transform xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output standalone='yes' indent='no'/><xsl:template match='/'><foo/></xsl:template></xsl:transform>");
283 xslt = new XslTransform ();
284 xslt.Load (doc, null, null);
285 reader = xslt.Transform (doc, null, new XmlUrlResolver ());
287 reader.Read (); // btw no XMLdecl output.
291 // http://www.w3.org/TR/xslt#section-Creating-Elements-with-xsl:element
292 // "If the namespace attribute is not present then the QName
293 // is expanded into an expanded-name using the namespace
294 // declarations in effect for the xsl:element element,
295 // including any default namespace declaration."
296 public void LREDefaultNamespace ()
298 string xsl = @"<xsl:stylesheet version='1.0'
299 xmlns='urn:foo' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
300 <xsl:template match='/*'>
301 <xsl:element name='{local-name()}' />
304 string xml = "<root/>";
305 XslTransform t = new XslTransform ();
306 t.Load (new XPathDocument (new StringReader (xsl)));
307 StringWriter sw = new StringWriter ();
308 XmlTextWriter xw = new XmlTextWriter (sw);
310 new XPathDocument (new StringReader (xml)),
312 AssertEquals ("<root xmlns=\"urn:foo\" />",
315 string xsl2 = @"<xsl:stylesheet version='1.0'
316 xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns='urn:foo'>
317 <xsl:template match='/*'>
319 <xsl:element name='{local-name()}' />
323 string xml2 = "<page/>";
324 t.Load (new XPathDocument (new StringReader (xsl2)));
325 sw = new StringWriter ();
326 xw = new XmlTextWriter (sw);
328 new XPathDocument (new StringReader (xml2)),
330 AssertEquals ("<root xmlns=\"urn:foo\"><page /></root>",