View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.xml;
16  
17  import java.net.URL;
18  
19  import org.htmlunit.MockWebConnection;
20  import org.htmlunit.WebDriverTestCase;
21  import org.htmlunit.junit.BrowserRunner;
22  import org.htmlunit.junit.annotation.Alerts;
23  import org.htmlunit.junit.annotation.HtmlUnitNYI;
24  import org.htmlunit.util.MimeType;
25  import org.junit.Test;
26  import org.junit.runner.RunWith;
27  
28  /**
29   * Tests for {@link XSLTProcessor}.
30   *
31   * @author Ahmed Ashour
32   * @author Ronald Brill
33   */
34  @RunWith(BrowserRunner.class)
35  public class XSLTProcessorTest extends WebDriverTestCase {
36  
37      /**
38       * @throws Exception if the test fails
39       */
40      @Test
41      @Alerts(DEFAULT = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
42                  + "<head></head><body> <h2>My CD Collection</h2> "
43                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul> </body></html>",
44              FF = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
45                  + "<body><h2>My CD Collection</h2>"
46                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>",
47              FF_ESR = "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
48                  + "<body><h2>My CD Collection</h2>"
49                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>")
50      @HtmlUnitNYI(CHROME = "<html><body><h2>My CD Collection</h2>"
51                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>",
52              EDGE = "<html><body><h2>My CD Collection</h2>"
53                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>",
54              FF = "<html><body><h2>My CD Collection</h2>"
55                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>",
56              FF_ESR = "<html><body><h2>My CD Collection</h2>"
57                  + "<ul><li>Empire Burlesque (Bob Dylan)</li></ul></body></html>")
58      public void transformToDocument() throws Exception {
59          final String html = DOCTYPE_HTML
60              + "<html><head>\n"
61              + "<script>\n"
62              + LOG_TITLE_FUNCTION
63  
64              + "  function  loadXMLDocument(url) {\n"
65              + "    var xhttp = new XMLHttpRequest();\n"
66              + "    xhttp.open('GET', url, false);\n"
67              + "    xhttp.send();\n"
68              + "    return xhttp.responseXML;\n"
69              + "  }"
70  
71              + "  function test() {\n"
72              + "    try {\n"
73              + "      var xmlDoc = loadXMLDocument('" + URL_SECOND + "1');\n"
74              + "      var xslDoc = loadXMLDocument('" + URL_SECOND + "2');\n"
75  
76              + "      var processor = new XSLTProcessor();\n"
77              + "      processor.importStylesheet(xslDoc);\n"
78              + "      var newDocument = processor.transformToDocument(xmlDoc);\n"
79              + "      log(new XMLSerializer().serializeToString(newDocument.documentElement));\n"
80              + "    } catch(e) { logEx(e); }\n"
81              + "  }\n"
82  
83              + "</script></head><body onload='test()'>\n"
84              + "</body></html>";
85  
86          final String xml
87              = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
88              + "<catalog>\n"
89              + "  <cd>\n"
90              + "    <title>Empire Burlesque</title>\n"
91              + "    <artist>Bob Dylan</artist>\n"
92              + "    <country>USA</country>\n"
93              + "    <company>Columbia</company>\n"
94              + "    <price>10.90</price>\n"
95              + "    <year>1985</year>\n"
96              + "  </cd>\n"
97              + "</catalog>";
98  
99          final String xsl
100             = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
101             + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
102             + "  <xsl:template match=\"/\">\n"
103             + "  <html>\n"
104             + "    <body>\n"
105             + "      <h2>My CD Collection</h2>\n"
106             + "      <ul>\n"
107             + "      <xsl:for-each select=\"catalog/cd\">\n"
108             + "        <li><xsl:value-of select='title'/> (<xsl:value-of select='artist'/>)</li>\n"
109             + "      </xsl:for-each>\n"
110             + "      </ul>\n"
111             + "    </body>\n"
112             + "  </html>\n"
113             + "  </xsl:template>\n"
114             + "</xsl:stylesheet>";
115 
116         final MockWebConnection conn = getMockWebConnection();
117         conn.setResponse(new URL(URL_SECOND, "1"), xml, MimeType.TEXT_XML);
118         conn.setResponse(new URL(URL_SECOND, "2"), xsl, MimeType.TEXT_XML);
119 
120         loadPageVerifyTitle2(html);
121     }
122 
123     /**
124      * @throws Exception if the test fails
125      */
126     @Test
127     @Alerts("*bar*")
128     public void transformToFragment() throws Exception {
129         final String xsl
130             = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
131             + "<xsl:template match=\"/\">*<xsl:value-of select=\"foo\" />*</xsl:template>"
132             + "</xsl:stylesheet>";
133 
134         final String html = DOCTYPE_HTML
135             + "<html><head>\n"
136             + "<script>\n"
137             + LOG_TITLE_FUNCTION
138 
139             + "  function test() {\n"
140             + "    try {\n"
141             + "      var xmlDoc = new DOMParser().parseFromString('<foo>bar</foo>', 'application/xml');\n"
142             + "      var xslDoc = new DOMParser().parseFromString('" + xsl + "', 'application/xml');\n"
143 
144             + "      var processor = new XSLTProcessor();\n"
145             + "      processor.importStylesheet(xslDoc);\n"
146             + "      var newFragment = processor.transformToFragment(xmlDoc, document);\n"
147             + "      log(new XMLSerializer().serializeToString(newFragment));\n"
148             + "    } catch(e) { logEx(e); }\n"
149             + "  }\n"
150 
151             + "</script></head><body onload='test()'>\n"
152             + "</body></html>";
153 
154         loadPageVerifyTitle2(html);
155     }
156 
157     /**
158      * @throws Exception if the test fails
159      */
160     @Test
161     @Alerts({"function", "function", "function", "function", "function",
162              "undefined", "undefined", "undefined", "undefined"})
163     public void methods() throws Exception {
164         final String html = DOCTYPE_HTML
165             + "<html><head>\n"
166             + "<script>\n"
167             + LOG_TITLE_FUNCTION
168             + "  function test() {\n"
169             + "    try {\n"
170             + "      if (XSLTProcessor) {\n"
171             + "        var processor = new XSLTProcessor();\n"
172             + "        log(typeof processor.importStylesheet);\n"
173             + "        log(typeof processor.transformToDocument);\n"
174             + "        log(typeof processor.transformToFragment);\n"
175             + "        log(typeof processor.setParameter);\n"
176             + "        log(typeof processor.getParameter);\n"
177             + "        log(typeof processor.input);\n"
178             + "        log(typeof processor.ouput);\n"
179             + "        log(typeof processor.addParameter);\n"
180             + "        log(typeof processor.transform);\n"
181             + "      } else {\n"
182             + "        log('XSLTProcessor not available');\n"
183             + "      }\n"
184             + "    } catch(e) { logEx(e); }\n"
185             + "  }\n"
186             + "</script></head><body onload='test()'>\n"
187             + "</body></html>";
188 
189         loadPageVerifyTitle2(html);
190     }
191 
192     /**
193      * @throws Exception if the test fails
194      */
195     @Test
196     @Alerts({"function", "function XSLTProcessor() { [native code] }",
197              "[object XSLTProcessor]"})
198     public void type() throws Exception {
199         final String html = DOCTYPE_HTML
200             + "<html><head>\n"
201             + "<script>\n"
202             + LOG_TITLE_FUNCTION
203             + "  function test() {\n"
204             + "    try {\n"
205             + "      log(typeof XSLTProcessor);\n"
206             + "      log(XSLTProcessor);\n"
207             + "      log(new XSLTProcessor());\n"
208             + "    } catch(e) { logEx(e) }\n"
209             + "  }\n"
210             + "</script></head><body onload='test()'>\n"
211             + "</body></html>";
212 
213         loadPageVerifyTitle2(html);
214     }
215 
216     /**
217      * @throws Exception if the test fails
218      */
219     @Test
220     @Alerts({"function XSLTProcessor() { [native code] }", "NaN", "true", "Yes", "Yes"})
221     public void browserDetection() throws Exception {
222         final String html = DOCTYPE_HTML
223             + "<html>\n"
224             + "<head>\n"
225             + "<script>\n"
226             + LOG_TITLE_FUNCTION
227             + "  function test() {\n"
228             + "    try {\n"
229             + "      log(String(XSLTProcessor));\n"
230             + "    } catch(e) { log('exception str'); }\n"
231             + "    try {\n"
232             + "      log(Number(XSLTProcessor));\n"
233             + "    } catch(e) { log('exception numb'); }\n"
234             + "    try {\n"
235             + "      log(Boolean(XSLTProcessor));\n"
236             + "    } catch(e) { log('exception bool'); }\n"
237             + "    try {\n"
238             + "      log(XSLTProcessor ? 'Yes' : 'No');\n"
239             + "    } catch(e) { log('exception ?'); }\n"
240             + "    try {\n"
241             + "      if (XSLTProcessor) { log('Yes') } else { log('No') }\n"
242             + "    } catch(e) { log('exception if'); }\n"
243             + "  }\n"
244             + "</script>\n"
245             + "</head>\n"
246             + "<body onload='test()'>\n"
247             + "</body></html>";
248         loadPageVerifyTitle2(html);
249     }
250 
251     /**
252      * @throws Exception if the test fails
253      */
254     @Test
255     @Alerts(DEFAULT = {"preparation done", "null"},
256             FF = {"preparation done", "exception "},
257             FF_ESR = {"preparation done", "exception "})
258     @HtmlUnitNYI(CHROME = {"preparation done", "exception InternalError"},
259             EDGE = {"preparation done", "exception InternalError"},
260             FF = {"preparation done", "exception InternalError"},
261             FF_ESR = {"preparation done", "exception InternalError"})
262     public void testSecurity() throws Exception {
263         final String html = DOCTYPE_HTML
264             + "<html><head>\n"
265             + "<script>\n"
266             + LOG_TITLE_FUNCTION
267 
268             + "  function  loadXMLDocument(url) {\n"
269             + "    var xhttp = new XMLHttpRequest();\n"
270             + "    xhttp.open('GET', url, false);\n"
271             + "    xhttp.send();\n"
272             + "    return xhttp.responseXML;\n"
273             + "  }"
274 
275             + "  function test() {\n"
276             + "    try {\n"
277             + "      var xmlDoc = loadXMLDocument('" + URL_SECOND + "1');\n"
278             + "      var xslDoc = loadXMLDocument('" + URL_SECOND + "2');\n"
279 
280             + "      var processor = new XSLTProcessor();\n"
281             + "      processor.importStylesheet(xslDoc);\n"
282             + "      log('preparation done');\n"
283             + "      var newDocument = processor.transformToDocument(xmlDoc);\n"
284             + "      log(newDocument);\n"
285             + "    } catch(e) { log('exception ' + e.name); }\n"
286             + "  }\n"
287             + "</script></head>"
288             + "<body onload='test()'>\n"
289             + "</body></html>";
290 
291         final String xml
292             = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
293             + "<s></s>";
294 
295         final String xsl
296             = " <xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" "
297                     + "xmlns:rt=\"http://xml.apache.org/xalan/java/java.lang.Runtime\" "
298                     + "xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\">\r\n"
299             + "    <xsl:template match='/'>\n"
300             + "      <xsl:variable name='rtobject' select='rt:getRuntime()'/>\n"
301             + "      <xsl:variable name=\"rtString\" select=\"ob:toString($rtobject)\"/>\n"
302             + "      <xsl:value-of select=\"$rtString\"/>\n"
303             + "    </xsl:template>\r\n"
304             + "  </xsl:stylesheet>";
305 
306         final MockWebConnection conn = getMockWebConnection();
307         conn.setResponse(new URL(URL_SECOND, "1"), xml, MimeType.TEXT_XML);
308         conn.setResponse(new URL(URL_SECOND, "2"), xsl, MimeType.TEXT_XML);
309 
310         loadPageVerifyTitle2(html);
311     }
312 }