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  import org.openqa.selenium.WebDriver;
28  
29  /**
30   * Tests for {@link XMLSerializer}.
31   *
32   * @author Ahmed Ashour
33   * @author Darrell DeBoer
34   * @author Frank Danek
35   * @author Ronald Brill
36   * @author Michael Anstis
37   */
38  @RunWith(BrowserRunner.class)
39  public class XMLSerializerTest extends WebDriverTestCase {
40  
41      /**
42       * @throws Exception if the test fails
43       */
44      @Test
45      @Alerts("<note>32<to>Tove</to>3210<from>Jani</from>321032<body>Do32not32forget32me32this32weekend!</body>"
46                      + "32<outer>10323232<inner>Some32Value</inner></outer>32</note>")
47      public void test() throws Exception {
48          final String expectedString = getExpectedAlerts()[0];
49          setExpectedAlerts();
50          final String serializationText =
51                  "<note> "
52                  + "<to>Tove</to> \\n"
53                  + "<from>Jani</from> \\n "
54                  + "<body>Do not forget me this weekend!</body> "
55                  + "<outer>\\n "
56                  + "  <inner>Some Value</inner>"
57                  + "</outer> "
58                  + "</note>";
59  
60          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
61          verifyTextArea2(driver, expectedString);
62      }
63  
64      /**
65       * @throws Exception if the test fails
66       */
67      @Test
68      @Alerts("<a><!--32abc32--></a>")
69      public void comment() throws Exception {
70          final String expectedString = getExpectedAlerts()[0];
71          setExpectedAlerts();
72          final String serializationText = "<a><!-- abc --></a>";
73          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
74          verifyTextArea2(driver, expectedString);
75      }
76  
77      /**
78       * @throws Exception if the test fails
79       */
80      @Test
81      @Alerts("<a>&lt;&gt;&amp;</a>")
82      public void xmlEntities() throws Exception {
83          final String expectedString = getExpectedAlerts()[0];
84          setExpectedAlerts();
85          final String serializationText = "<a>&lt;&gt;&amp;</a>";
86          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
87          verifyTextArea2(driver, expectedString);
88      }
89  
90      /**
91       * @throws Exception if the test fails
92       */
93      @Test
94      @Alerts(DEFAULT = "<?xml32version=\"1.0\"32encoding=\"UTF-8\"?>1310<xsl:stylesheet32version=\"1.0\"32"
95                      + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
96                      + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>",
97              CHROME = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><xsl:stylesheet32xmlns:xsl="
98                      + "\"http://www.w3.org/1999/XSL/Transform\"32version=\"1.0\">103232<xsl:template32"
99                      + "match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>103232"
100                     + "</xsl:template>10</xsl:stylesheet>",
101             EDGE = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><xsl:stylesheet32xmlns:xsl="
102                     + "\"http://www.w3.org/1999/XSL/Transform\"32version=\"1.0\">103232<xsl:template32"
103                     + "match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>103232"
104                     + "</xsl:template>10</xsl:stylesheet>")
105     @HtmlUnitNYI(CHROME = "<xsl:stylesheet32version=\"1.0\"32xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
106                     + "103232<xsl:template32match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>"
107                     + "103232</xsl:template>10</xsl:stylesheet>",
108             EDGE = "<xsl:stylesheet32version=\"1.0\"32xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
109                     + "103232<xsl:template32match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>"
110                     + "103232</xsl:template>10</xsl:stylesheet>",
111             FF_ESR = "<xsl:stylesheet32version=\"1.0\"32"
112                     + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
113                     + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>",
114             FF = "<xsl:stylesheet32version=\"1.0\"32"
115                     + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
116                     + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>")
117     public void nameSpaces() throws Exception {
118         final String expectedString = getExpectedAlerts()[0];
119         setExpectedAlerts();
120         final String serializationText =
121                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\\n"
122                 + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\\n"
123                 + "  <xsl:template match=\"/\">\\n"
124                 + "  <html>\\n"
125                 + "    <body>\\n"
126                 + "    </body>\\n"
127                 + "  </html>\\n"
128                 + "  </xsl:template>\\n"
129                 + "</xsl:stylesheet>";
130 
131         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
132         verifyTextArea2(driver, expectedString);
133     }
134 
135     /**
136      * @throws Exception if the test fails
137      */
138     @Test
139     @Alerts("<document32attrib=\"attribValue\"><outer32attrib=\"attribValue\">"
140                 + "<inner32attrib=\"attribValue\"/><meta32attrib=\"attribValue\"/></outer></document>")
141     public void attributes() throws Exception {
142         final String expectedString = getExpectedAlerts()[0];
143         setExpectedAlerts();
144         final String serializationText = "<document attrib=\"attribValue\">"
145                                             + "<outer attrib=\"attribValue\">"
146                                             + "<inner attrib=\"attribValue\"/>"
147                                             + "<meta attrib=\"attribValue\"/>"
148                                             + "</outer></document>";
149 
150         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
151         verifyTextArea2(driver, expectedString);
152     }
153 
154     /**
155      * @throws Exception if the test fails
156      */
157     @Test
158     @Alerts(DEFAULT = "<?xml32version=\"1.0\"32encoding=\"UTF-8\"?>1310<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
159                     + "<head><title>html</title></head>"
160                     + "<body32id=\"bodyId\">"
161                     + "<span32class=\"spanClass\">foo</span>"
162                     + "</body>"
163                     + "</html>",
164             CHROME = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><html32xmlns=\"http://www.w3.org/1999/xhtml\">"
165                     + "<head><title>html</title></head>"
166                     + "<body32id=\"bodyId\">"
167                     + "<span32class=\"spanClass\">foo</span>"
168                     + "</body>"
169                     + "</html>",
170             EDGE = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><html32xmlns=\"http://www.w3.org/1999/xhtml\">"
171                     + "<head><title>html</title></head>"
172                     + "<body32id=\"bodyId\">"
173                     + "<span32class=\"spanClass\">foo</span>"
174                     + "</body>"
175                     + "</html>")
176     @HtmlUnitNYI(CHROME = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
177                     + "<head><title>html</title></head>"
178                     + "<body32id=\"bodyId\">"
179                     + "<span32class=\"spanClass\">foo</span>"
180                     + "</body>"
181                     + "</html>",
182             EDGE = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
183                     + "<head><title>html</title></head>"
184                     + "<body32id=\"bodyId\">"
185                     + "<span32class=\"spanClass\">foo</span>"
186                     + "</body>"
187                     + "</html>",
188             FF_ESR = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
189                     + "<head><title>html</title></head>"
190                     + "<body32id=\"bodyId\">"
191                     + "<span32class=\"spanClass\">foo</span>"
192                     + "</body>"
193                     + "</html>",
194             FF = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
195                     + "<head><title>html</title></head>"
196                     + "<body32id=\"bodyId\">"
197                     + "<span32class=\"spanClass\">foo</span>"
198                     + "</body>"
199                     + "</html>")
200     public void htmlAttributes() throws Exception {
201         final String expectedString = getExpectedAlerts()[0];
202         setExpectedAlerts();
203         final String serializationText = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
204                                           + "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
205                                           + "<head><title>html</title></head>"
206                                           + "<body id=\"bodyId\">"
207                                           + "<span class=\"spanClass\">foo</span>"
208                                           + "</body>"
209                                           + "</html>";
210 
211         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
212         verifyTextArea2(driver, expectedString);
213     }
214 
215     /**
216      * Constructs an HTML page that when loaded will parse and serialize the provided text.
217      * First the provided text is parsed into a Document. Then the Document is serialized (browser-specific).
218      * Finally the result is placed into the text area "myTextArea".
219      */
220     private static String constructPageContent(final String serializationText) {
221         final String escapedText = serializationText.replace("\n", "\\n");
222 
223         final StringBuilder builder = new StringBuilder();
224         builder.append(
225               "<html><head>\n"
226             + "<script>\n"
227             + LOG_TITLE_FUNCTION
228             + "  function test() {\n");
229 
230         builder.append("    var text = '").append(escapedText).append("';\n").append(
231               "    var doc = " + XMLDocumentTest.callLoadXMLDocumentFromString("text") + ";\n"
232             + "    var xml = " + XMLDocumentTest.callSerializeXMLDocumentToString("doc") + ";\n"
233             + "    var ta = document.getElementById('myLog');\n"
234             + "    for (var i = 0; i < xml.length; i++) {\n"
235             + "      if (xml.charCodeAt(i) < 33)\n"
236             + "        ta.value += xml.charCodeAt(i);\n"
237             + "      else\n"
238             + "        ta.value += xml.charAt(i);\n"
239             + "    }\n"
240             + "    ta.value += '\\u00a7';\n"
241             + "  }\n"
242             + XMLDocumentTest.LOAD_XML_DOCUMENT_FROM_STRING_FUNCTION
243             + XMLDocumentTest.SERIALIZE_XML_DOCUMENT_TO_STRING_FUNCTION
244             + "</script></head><body onload='test()'>\n"
245             + LOG_TEXTAREA
246             + "</body></html>");
247         return builder.toString();
248     }
249 
250     /**
251      * @throws Exception if the test fails
252      */
253     @Test
254     @Alerts({"<html xmlns=\"http://www.w3.org/1999/xhtml\"><body id=\"bodyId\"></body></html>",
255              "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body id=\"bodyId\"></body></html>"})
256     @HtmlUnitNYI(CHROME = {"<html><body id=\"bodyId\"></body></html>",
257                            "<html><body id=\"bodyId\"></body></html>"},
258             EDGE = {"<html><body id=\"bodyId\"></body></html>",
259                     "<html><body id=\"bodyId\"></body></html>"},
260             FF = {"<html><body id=\"bodyId\"></body></html>",
261                   "<html><body id=\"bodyId\"></body></html>"},
262             FF_ESR = {"<html><body id=\"bodyId\"></body></html>",
263                       "<html><body id=\"bodyId\"></body></html>"})
264     public void xhtmlDocument() throws Exception {
265         final String html = DOCTYPE_HTML
266             + "<html><head>\n"
267             + "<script>\n"
268             + LOG_TITLE_FUNCTION
269             + "function test() {\n"
270             + "  var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);\n"
271             + "  var body = document.createElementNS('http://www.w3.org/1999/xhtml', 'body');\n"
272             + "  body.setAttribute('id', 'bodyId');\n"
273             + "  doc.documentElement.appendChild(body);"
274 
275             + "  log(new XMLSerializer().serializeToString(doc));\n"
276             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
277             + "}\n"
278             + "</script></head><body onload='test()'>\n"
279             + "</body></html>";
280         loadPageVerifyTitle2(html);
281     }
282 
283     /**
284      * @throws Exception if the test fails
285      */
286     @Test
287     @Alerts({"<html xmlns=\"http://www.w3.org/1999/xhtml\"><body xmlns=\"\" id=\"bodyId\"/></html>",
288              "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body xmlns=\"\" id=\"bodyId\"/></html>"})
289     @HtmlUnitNYI(CHROME = {"<html><body id=\"bodyId\"></body></html>",
290                            "<html><body id=\"bodyId\"></body></html>"},
291             EDGE = {"<html><body id=\"bodyId\"></body></html>",
292                     "<html><body id=\"bodyId\"></body></html>"},
293             FF = {"<html><body id=\"bodyId\"></body></html>",
294                   "<html><body id=\"bodyId\"></body></html>"},
295             FF_ESR = {"<html><body id=\"bodyId\"></body></html>",
296                       "<html><body id=\"bodyId\"></body></html>"})
297     public void xhtmlDocumentBodyEmptyNamespace() throws Exception {
298         final String html = DOCTYPE_HTML
299             + "<html><head>\n"
300             + "<script>\n"
301             + LOG_TITLE_FUNCTION
302             + "function test() {\n"
303             + "  var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);\n"
304             + "  var body = document.createElementNS('', 'body');\n"
305             + "  body.setAttribute('id', 'bodyId');\n"
306             + "  doc.documentElement.appendChild(body);"
307 
308             + "  log(new XMLSerializer().serializeToString(doc));\n"
309             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
310             + "}\n"
311             + "</script></head><body onload='test()'>\n"
312             + "</body></html>";
313         loadPageVerifyTitle2(html);
314     }
315 
316 
317     /**
318      * @throws Exception if the test fails
319      */
320     @Test
321     @Alerts({"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body/></soap:Envelope>",
322              "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body/></soap:Envelope>"})
323     @HtmlUnitNYI(CHROME = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
324                            "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
325             EDGE = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
326                     "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
327             FF = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
328                   "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
329             FF_ESR = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
330                       "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"})
331     public void soapTest() throws Exception {
332         final String html = DOCTYPE_HTML
333             + "<html><head>\n"
334             + "<script>\n"
335             + LOG_TITLE_FUNCTION
336             + "function test() {\n"
337             + "  var dom = document.implementation.createDocument('http://schemas.xmlsoap.org/soap/envelope/', 'soap:Envelope', null);\n"
338 
339             + "  var soapEnv = dom.documentElement;\n"
340             + "  soapBody = dom.createElementNS('http://schemas.xmlsoap.org/soap/envelope/', 'Body');\n"
341             + "  soapEnv.appendChild(soapBody);"
342 
343             + "  log(new XMLSerializer().serializeToString(dom));\n"
344             + "  log(new XMLSerializer().serializeToString(dom.documentElement));\n"
345             + "}\n"
346             + "</script></head><body onload='test()'>\n"
347             + "</body></html>";
348         loadPageVerifyTitle2(html);
349     }
350 
351     /**
352      * @throws Exception if the test fails
353      */
354     @Test
355     @Alerts({"<foo/>", "<foo/>"})
356     public void document() throws Exception {
357         final String html = DOCTYPE_HTML
358             + "<html><head>\n"
359             + "<script>\n"
360             + LOG_TITLE_FUNCTION
361             + "function test() {\n"
362             + "  var doc = document.implementation.createDocument('', 'foo', null);\n"
363             + "  log(new XMLSerializer().serializeToString(doc));\n"
364             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
365             + "}\n"
366             + "</script></head><body onload='test()'>\n"
367             + "</body></html>";
368         loadPageVerifyTitle2(html);
369     }
370 
371     /**
372      * @throws Exception if the test fails
373      */
374     @Test
375     @Alerts("#")
376     public void emptyDocumentFragment() throws Exception {
377         final String html = DOCTYPE_HTML
378             + "<html><head>\n"
379             + "<script>\n"
380             + LOG_TITLE_FUNCTION
381             + "function test() {\n"
382             + "  var fragment = document.createDocumentFragment();\n"
383             + "  log('#' + new XMLSerializer().serializeToString(fragment));\n"
384             + "}\n"
385             + "</script></head><body onload='test()'>\n"
386             + "</body></html>";
387         loadPageVerifyTitle2(html);
388     }
389 
390     /**
391      * @throws Exception if the test fails
392      */
393     @Test
394     @Alerts("<h1 xmlns=\"http://www.w3.org/1999/xhtml\">HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\">is great</h2>")
395     @HtmlUnitNYI(CHROME = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
396             EDGE = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
397             FF = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
398             FF_ESR = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>")
399     public void documentFragment() throws Exception {
400         final String html = DOCTYPE_HTML
401             + "<html><head>\n"
402             + "<script>\n"
403             + LOG_TITLE_FUNCTION
404             + "function test() {\n"
405             + "  var fragment = document.createDocumentFragment();\n"
406 
407             + "  var heading = document.createElement('h1');\n"
408             + "  heading.textContent = 'HtmlUnit';\n"
409             + "  fragment.appendChild(heading);\n"
410 
411             + "  heading = document.createElement('h2');\n"
412             + "  heading.textContent = 'is great';\n"
413             + "  fragment.appendChild(heading);\n"
414 
415             + "  log(new XMLSerializer().serializeToString(fragment));\n"
416             + "}\n"
417             + "</script></head><body onload='test()'>\n"
418             + "</body></html>";
419         loadPageVerifyTitle2(html);
420     }
421 
422     /**
423      * @throws Exception if the test fails
424      */
425     @Test
426     @Alerts({"<img/>", "<img xmlns=\"http://www.w3.org/1999/xhtml\" />", "<?myTarget myData?>"})
427     public void xml() throws Exception {
428         final String html = DOCTYPE_HTML
429             + "<html><head>\n"
430             + "<script>\n"
431             + LOG_TITLE_FUNCTION
432             + "  function test() {\n"
433             + "    var doc = document.implementation.createDocument('', '', null);\n"
434             + "    testFragment(doc);\n"
435             + "    testFragment(document);\n"
436             + "    var pi = doc.createProcessingInstruction('myTarget', 'myData');\n"
437             + "    log(new XMLSerializer().serializeToString(pi));\n"
438             + "  }\n"
439             + "  function testFragment(doc) {\n"
440             + "    var fragment = doc.createDocumentFragment();\n"
441             + "    var img = doc.createElement('img');\n"
442             + "    fragment.appendChild(img);\n"
443             + "    log(new XMLSerializer().serializeToString(fragment));\n"
444             + "  }\n"
445             + "</script></head><body onload='test()'>\n"
446             + "</body></html>";
447         loadPageVerifyTitle2(html);
448     }
449 
450     /**
451      * @throws Exception if the test fails
452      */
453     @Test
454     @Alerts("<root><my:parent xmlns:my=\"myUri\"><my:child/><another_child/></my:parent></root>")
455     public void namespace() throws Exception {
456         final String html = DOCTYPE_HTML
457             + "<html><head>\n"
458             + "<script>\n"
459             + LOG_TITLE_FUNCTION
460             + "  function test() {\n"
461             + "    var doc = document.implementation.createDocument('', '', null);\n"
462             + "    var root = doc.createElement('root');\n"
463             + "    doc.appendChild(root);\n"
464             + "    var parent = createNS(doc, 'my:parent', 'myUri');\n"
465             + "    root.appendChild(parent);\n"
466             + "    parent.appendChild(createNS(doc, 'my:child', 'myUri'));\n"
467             + "    parent.appendChild(doc.createElement('another_child'));\n"
468             + "    log(" + XMLDocumentTest.callSerializeXMLDocumentToString("doc") + ");\n"
469             + "  }\n"
470             + "  function createNS(doc, name, uri) {\n"
471             + "    return typeof doc.createNode == 'function' || typeof doc.createNode == 'unknown' ? "
472             + "doc.createNode(1, name, uri) : doc.createElementNS(uri, name);\n"
473             + "  }\n"
474             + XMLDocumentTest.SERIALIZE_XML_DOCUMENT_TO_STRING_FUNCTION
475             + "</script></head><body onload='test()'>\n"
476             + "</body></html>";
477         loadPageVerifyTitle2(html);
478     }
479 
480     /**
481      * @throws Exception if the test fails
482      */
483     @Test
484     @Alerts("<textarea xmlns=\"http://www.w3.org/1999/xhtml\"></textarea>")
485     public void mixedCase() throws Exception {
486         final String html = DOCTYPE_HTML
487             + "<html><head>\n"
488             + "<script>\n"
489             + LOG_TITLE_FUNCTION
490             + "  function test() {\n"
491             + "    var t = document.createElement('teXtaREa');\n"
492             + "    log(new XMLSerializer().serializeToString(t));\n"
493             + "  }\n"
494             + "</script></head><body onload='test()'>\n"
495             + "</body></html>";
496         loadPageVerifyTitle2(html);
497     }
498 
499     /**
500      * @throws Exception if the test fails
501      */
502     @Test
503     @Alerts({"<area xmlns=\"http://www.w3.org/1999/xhtml\" />",
504              "<base xmlns=\"http://www.w3.org/1999/xhtml\" />",
505              "<basefont xmlns=\"http://www.w3.org/1999/xhtml\" />",
506              "<br xmlns=\"http://www.w3.org/1999/xhtml\" />",
507              "<hr xmlns=\"http://www.w3.org/1999/xhtml\" />",
508              "<input xmlns=\"http://www.w3.org/1999/xhtml\" />",
509              "<link xmlns=\"http://www.w3.org/1999/xhtml\" />",
510              "<meta xmlns=\"http://www.w3.org/1999/xhtml\" />"})
511     public void noClosingTag() throws Exception {
512         final String html = DOCTYPE_HTML
513             + "<html><head>\n"
514             + "<script>\n"
515             + LOG_TITLE_FUNCTION
516             + "  function test() {\n"
517             + "    var t = document.createElement('area');\n"
518             + "    log(new XMLSerializer().serializeToString(t));\n"
519             + "    var t = document.createElement('base');\n"
520             + "    log(new XMLSerializer().serializeToString(t));\n"
521             + "    var t = document.createElement('basefont');\n"
522             + "    log(new XMLSerializer().serializeToString(t));\n"
523             + "    var t = document.createElement('br');\n"
524             + "    log(new XMLSerializer().serializeToString(t));\n"
525             + "    var t = document.createElement('hr');\n"
526             + "    log(new XMLSerializer().serializeToString(t));\n"
527             + "    var t = document.createElement('input');\n"
528             + "    log(new XMLSerializer().serializeToString(t));\n"
529             + "    var t = document.createElement('link');\n"
530             + "    log(new XMLSerializer().serializeToString(t));\n"
531             + "    var t = document.createElement('meta');\n"
532             + "    log(new XMLSerializer().serializeToString(t));\n"
533             + "  }\n"
534             + "</script></head><body onload='test()'>\n"
535             + "</body></html>";
536         loadPageVerifyTitle2(html);
537     }
538 
539     /**
540      * There is a small difference between HtmlUnit and FF.
541      * HtmlUnit adds type=text per default to the input
542      * FF handles input without type as type=text
543      * the fix for this is too big, so i made this workaround
544      * and add another (not yet implemented) test
545      *
546      * @throws Exception if the test fails
547      */
548     @Test
549     @Alerts("<input xmlns=\"http://www.w3.org/1999/xhtml\" />")
550     public void inputTagWithoutType() throws Exception {
551         final String html = DOCTYPE_HTML
552             + "<html><head>\n"
553             + "<script>\n"
554             + LOG_TITLE_FUNCTION
555             + "  function test() {\n"
556             + "    var t = document.createElement('input');\n"
557             + "    log(new XMLSerializer().serializeToString(t));\n"
558             + "  }\n"
559             + "</script></head><body onload='test()'>\n"
560             + "</body></html>";
561         loadPageVerifyTitle2(html);
562     }
563 
564     /**
565      * Test for some not self closing tags.
566      *
567      * @throws Exception if the test fails
568      */
569     @Test
570     @Alerts({"<div xmlns=\"http://www.w3.org/1999/xhtml\"></div>",
571              "<h1 xmlns=\"http://www.w3.org/1999/xhtml\"></h1>",
572              "<p xmlns=\"http://www.w3.org/1999/xhtml\"></p>",
573              "<li xmlns=\"http://www.w3.org/1999/xhtml\"></li>",
574              "<textarea xmlns=\"http://www.w3.org/1999/xhtml\"></textarea>"})
575     public void otherTags() throws Exception {
576         final String html = DOCTYPE_HTML
577             + "<html><head>\n"
578             + "<script>\n"
579             + LOG_TITLE_FUNCTION
580             + "  function test() {\n"
581             + "    var t = document.createElement('div');\n"
582             + "    log(new XMLSerializer().serializeToString(t));\n"
583             + "    var t = document.createElement('h1');\n"
584             + "    log(new XMLSerializer().serializeToString(t));\n"
585             + "    var t = document.createElement('p');\n"
586             + "    log(new XMLSerializer().serializeToString(t));\n"
587             + "    var t = document.createElement('li');\n"
588             + "    log(new XMLSerializer().serializeToString(t));\n"
589             + "    var t = document.createElement('textarea');\n"
590             + "    log(new XMLSerializer().serializeToString(t));\n"
591             + "  }\n"
592             + "</script></head><body onload='test()'>\n"
593             + "</body></html>";
594         loadPageVerifyTitle2(html);
595     }
596 
597     /**
598      * @throws Exception if the test fails
599      */
600     @Test
601     @Alerts("<img xmlns=\"http://www.w3.org/1999/xhtml\" href=\"mypage.htm\" />")
602     public void noClosingTagWithAttribute() throws Exception {
603         final String html = DOCTYPE_HTML
604             + "<html><head>\n"
605             + "<script>\n"
606             + LOG_TITLE_FUNCTION
607             + "  function test() {\n"
608             + "    var t = document.createElement('img');\n"
609             + "    t.setAttribute('href', 'mypage.htm');\n"
610             + "    log(new XMLSerializer().serializeToString(t));\n"
611             + "  }\n"
612             + "</script></head><body onload='test()'>\n"
613             + "</body></html>";
614         loadPageVerifyTitle2(html);
615     }
616 
617     /**
618      * @throws Exception if the test fails
619      */
620     @Test
621     @Alerts(CHROME = "<catalog>\n"
622                     + "  <cd>\n"
623                     + "    <title>Empire Burlesque</title>\n"
624                     + "    <artist>Bob Dylan \u1042</artist>\n"
625                     + "  </cd>\n"
626                     + "</catalog>",
627             EDGE = "<catalog>\n"
628                     + "  <cd>\n"
629                     + "    <title>Empire Burlesque</title>\n"
630                     + "    <artist>Bob Dylan \u1042</artist>\n"
631                     + "  </cd>\n"
632                     + "</catalog>",
633             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
634                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
635             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
636                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
637     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
638             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
639     public void outputXmlIndent() throws Exception {
640         transform("<xsl:output method='xml' indent='yes' />");
641     }
642 
643     /**
644      * @throws Exception if the test fails
645      */
646     @Test
647     @Alerts(CHROME = "<catalog>\n"
648                     + "  <cd>\n"
649                     + "    <title>Empire Burlesque</title>\n"
650                     + "    <artist>Bob Dylan \u1042</artist>\n"
651                     + "  </cd>\n"
652                     + "</catalog>",
653             EDGE = "<catalog>\n"
654                     + "  <cd>\n"
655                     + "    <title>Empire Burlesque</title>\n"
656                     + "    <artist>Bob Dylan \u1042</artist>\n"
657                     + "  </cd>\n"
658                     + "</catalog>",
659             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
660                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
661             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
662                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
663     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
664             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
665     public void outputIndent() throws Exception {
666         transform("<xsl:output indent='yes' />");
667     }
668 
669     /**
670      * @throws Exception if the test fails
671      */
672     @Test
673     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
674             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
675             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
676                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
677             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
678                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
679     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
680             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
681     public void outputNoIndent() throws Exception {
682         transform("<xsl:output indent='no' />");
683     }
684 
685     /**
686      * @throws Exception if the test fails
687      */
688     @Test
689     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
690             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
691             FF = "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
692                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
693             FF_ESR = "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
694                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
695     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
696             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
697     public void outputEncoding1252() throws Exception {
698         transform("<xsl:output encoding='Windows-1252' />");
699     }
700 
701     /**
702      * @throws Exception if the test fails
703      */
704     @Test
705     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
706             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
707             FF = "<?xml version=\"1.0\" encoding=\"windows-1251\"?>\n"
708                 + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
709             FF_ESR = "<?xml version=\"1.0\" encoding=\"windows-1251\"?>\n"
710                 + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
711     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
712             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
713     public void outputEncoding1251() throws Exception {
714         transform("<xsl:output encoding='Windows-1251' />");
715     }
716 
717     /**
718      * @throws Exception if the test fails
719      */
720     @Test
721     @Alerts("<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
722     public void outputOmitXmlDeclaration() throws Exception {
723         transform("<xsl:output omit-xml-declaration='yes' />");
724     }
725 
726     /**
727      * @throws Exception if the test fails
728      */
729     @Test
730     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
731             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
732             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
733                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
734             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
735                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
736     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
737             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
738     public void noOutput() throws Exception {
739         transform("");
740     }
741 
742     private void transform(final String xslOutput) throws Exception {
743         final String xml
744                 = "<?xml version='1.0' encoding='ISO-8859-1'?>"
745                 + "<catalog><cd><title>Empire Burlesque</title>"
746                 + "<artist>Bob Dylan &#x1042;</artist>"
747                 + "</cd>"
748                 + "</catalog>";
749 
750         final String xsl
751                 = "<?xml version='1.0' encoding='ISO-8859-1'?>"
752                 + "<xsl:stylesheet version='1.0' "
753                 + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >"
754                 + "  " + xslOutput
755                 + "  <xsl:template match='@*|node()'>"
756                 + "    <xsl:copy>"
757                 + "      <xsl:apply-templates select='@*|node()'/>"
758                 + "    </xsl:copy>"
759                 + "  </xsl:template>"
760                 + "</xsl:stylesheet>";
761 
762         final String html = DOCTYPE_HTML
763                 + "<html><head><title>foo</title><script>\n"
764                 + "  function test() {\n"
765                 + "    var ta = document.getElementById('myLog');\n"
766                 + "    try {\n"
767                 + "      var xsltProcessor = new XSLTProcessor();\n"
768                 + "      var xmlDoc = new DOMParser().parseFromString(\"" + xml + "\", \"application/xml\");\n"
769                 + "      var xsltDoc = new DOMParser().parseFromString(\"" + xsl + "\", \"application/xml\");\n"
770                 + "      xsltProcessor.importStylesheet(xsltDoc);\n"
771                 + "      var resultDocument = xsltProcessor.transformToDocument(xmlDoc);\n"
772                 + "      var xml = new XMLSerializer().serializeToString(resultDocument);\n"
773                 + "      ta.value = xml + '\\u00a7';\n"
774                 + "    } catch(e) { ta.value = 'exception'; }\n"
775                 + "  }\n"
776                 + "</script></head>\n"
777                 + "<body onload='test()'>\n"
778                 + LOG_TEXTAREA
779                 + "</body></html>";
780 
781         final MockWebConnection conn = getMockWebConnection();
782         conn.setResponse(new URL(URL_SECOND, "1"), xml, MimeType.TEXT_XML);
783         conn.setResponse(new URL(URL_SECOND, "2"), xsl, MimeType.TEXT_XML);
784 
785         final WebDriver driver = loadPage2(html);
786 
787         verifyTextArea2(driver, getExpectedAlerts()[0]);
788     }
789 }