1 /* 2 * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package transform; 25 26 import static jaxp.library.JAXPTestUtilities.getSystemProperty; 27 28 import java.io.BufferedReader; 29 import java.io.ByteArrayInputStream; 30 import java.io.ByteArrayOutputStream; 31 import java.io.File; 32 import java.io.FileNotFoundException; 33 import java.io.FileReader; 34 import java.io.IOException; 35 import java.io.StringReader; 36 import java.io.StringWriter; 37 38 import javax.xml.parsers.DocumentBuilderFactory; 39 import javax.xml.parsers.ParserConfigurationException; 40 import javax.xml.parsers.SAXParserFactory; 41 import javax.xml.stream.XMLInputFactory; 42 import javax.xml.stream.XMLStreamException; 43 import javax.xml.transform.Source; 44 import javax.xml.transform.Templates; 45 import javax.xml.transform.Transformer; 46 import javax.xml.transform.TransformerConfigurationException; 47 import javax.xml.transform.TransformerException; 48 import javax.xml.transform.TransformerFactory; 49 import javax.xml.transform.dom.DOMResult; 50 import javax.xml.transform.dom.DOMSource; 51 import javax.xml.transform.sax.SAXSource; 52 import javax.xml.transform.stax.StAXSource; 53 import javax.xml.transform.stream.StreamResult; 54 import javax.xml.transform.stream.StreamSource; 55 56 import org.testng.Assert; 57 import org.testng.AssertJUnit; 58 import org.testng.annotations.DataProvider; 59 import org.testng.annotations.Listeners; 60 import org.testng.annotations.Test; 61 import org.w3c.dom.Document; 62 import org.w3c.dom.Element; 63 import org.w3c.dom.Node; 64 import org.w3c.dom.NodeList; 65 import org.xml.sax.ContentHandler; 66 import org.xml.sax.DTDHandler; 67 import org.xml.sax.EntityResolver; 68 import org.xml.sax.ErrorHandler; 69 import org.xml.sax.InputSource; 70 import org.xml.sax.SAXException; 71 import org.xml.sax.SAXNotRecognizedException; 72 import org.xml.sax.SAXNotSupportedException; 73 import org.xml.sax.XMLReader; 74 import org.xml.sax.helpers.AttributesImpl; 75 76 import com.sun.org.apache.xml.internal.serialize.OutputFormat; 77 import com.sun.org.apache.xml.internal.serialize.XMLSerializer; 78 79 /* 80 * @test 81 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest 82 * @run testng/othervm -DrunSecMngr=true transform.TransformerTest 83 * @run testng/othervm transform.TransformerTest 84 * @summary Transformer Tests 85 * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169631 8169772 8172974 86 */ 87 @Listeners({jaxp.library.FilePolicy.class}) 88 public class TransformerTest { 89 90 // some global constants 91 private static final String LINE_SEPARATOR = 92 getSystemProperty("line.separator"); 93 94 private static final String NAMESPACES = 95 "http://xml.org/sax/features/namespaces"; 96 97 private static final String NAMESPACE_PREFIXES = 98 "http://xml.org/sax/features/namespace-prefixes"; 99 100 private static abstract class TestTemplate { 101 protected static void printSnippet(String title, String snippet) { 102 StringBuilder div = new StringBuilder(); 103 for (int i = 0; i < title.length(); i++) 104 div.append("="); 105 System.out.println(title + "\n" + div + "\n" + snippet + "\n"); 106 } 107 } 108 109 /** 110 * Reads the contents of the given file into a string. 111 * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one. 112 * 113 * @param f 114 * The file to read 115 * @return The content of the file as a string, with line terminators as \"n" 116 * for all platforms 117 * @throws IOException 118 * If there was an error reading 119 */ 120 private String getFileContentAsString(File f) throws IOException { 121 try (BufferedReader reader = new BufferedReader(new FileReader(f))) { 122 String line; 123 StringBuilder sb = new StringBuilder(); 124 while ((line = reader.readLine()) != null) { 125 sb.append(line).append("\n"); 126 } 127 return sb.toString(); 128 } 129 } 130 131 private class XMLReaderFor6305029 implements XMLReader { 132 private boolean namespaces = true; 133 private boolean namespacePrefixes = false; 134 private EntityResolver resolver; 135 private DTDHandler dtdHandler; 136 private ContentHandler contentHandler; 137 private ErrorHandler errorHandler; 138 139 public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { 140 if (name.equals(NAMESPACES)) { 141 return namespaces; 142 } else if (name.equals(NAMESPACE_PREFIXES)) { 143 return namespacePrefixes; 144 } else { 145 throw new SAXNotRecognizedException(); 146 } 147 } 148 149 public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { 150 if (name.equals(NAMESPACES)) { 151 namespaces = value; 152 } else if (name.equals(NAMESPACE_PREFIXES)) { 153 namespacePrefixes = value; 154 } else { 155 throw new SAXNotRecognizedException(); 156 } 157 } 158 159 public Object getProperty(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { 160 return null; 161 } 162 163 public void setProperty(final String name, final Object value) throws SAXNotRecognizedException, SAXNotSupportedException { 164 } 165 166 public void setEntityResolver(final EntityResolver theResolver) { 167 this.resolver = theResolver; 168 } 169 170 public EntityResolver getEntityResolver() { 171 return resolver; 172 } 173 174 public void setDTDHandler(final DTDHandler theHandler) { 175 dtdHandler = theHandler; 176 } 177 178 public DTDHandler getDTDHandler() { 179 return dtdHandler; 180 } 181 182 public void setContentHandler(final ContentHandler handler) { 183 contentHandler = handler; 184 } 185 186 public ContentHandler getContentHandler() { 187 return contentHandler; 188 } 189 190 public void setErrorHandler(final ErrorHandler handler) { 191 errorHandler = handler; 192 } 193 194 public ErrorHandler getErrorHandler() { 195 return errorHandler; 196 } 197 198 public void parse(final InputSource input) throws IOException, SAXException { 199 parse(); 200 } 201 202 public void parse(final String systemId) throws IOException, SAXException { 203 parse(); 204 } 205 206 private void parse() throws SAXException { 207 contentHandler.startDocument(); 208 contentHandler.startPrefixMapping("prefix", "namespaceUri"); 209 210 AttributesImpl atts = new AttributesImpl(); 211 if (namespacePrefixes) { 212 atts.addAttribute("", "xmlns:prefix", "xmlns:prefix", "CDATA", "namespaceUri"); 213 } 214 215 contentHandler.startElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "", atts); 216 contentHandler.endElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : ""); 217 contentHandler.endPrefixMapping("prefix"); 218 contentHandler.endDocument(); 219 } 220 } 221 222 /* 223 * @bug 6272879 224 * @summary Test for JDK-6272879 225 */ 226 @Test 227 public final void testBug6272879() throws IOException, TransformerException { 228 final String xsl = 229 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR + 230 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR + 231 "<xsl:output method=\"xml\" indent=\"no\" encoding=\"ISO-8859-1\"/>" + LINE_SEPARATOR + 232 "<xsl:template match=\"/\">" + LINE_SEPARATOR + 233 "<xsl:element name=\"TransformateurXML\">" + LINE_SEPARATOR + 234 " <xsl:for-each select=\"XMLUtils/test\">" + LINE_SEPARATOR + 235 " <xsl:element name=\"test2\">" + LINE_SEPARATOR + 236 " <xsl:element name=\"valeur2\">" + LINE_SEPARATOR + 237 " <xsl:attribute name=\"attribut2\">" + LINE_SEPARATOR + 238 " <xsl:value-of select=\"valeur/@attribut\"/>" + LINE_SEPARATOR + 239 " </xsl:attribute>" + LINE_SEPARATOR + 240 " <xsl:value-of select=\"valeur\"/>" + LINE_SEPARATOR + 241 " </xsl:element>" + LINE_SEPARATOR + 242 " </xsl:element>" + LINE_SEPARATOR + 243 " </xsl:for-each>" + LINE_SEPARATOR + 244 "</xsl:element>" + LINE_SEPARATOR + 245 "</xsl:template>" + LINE_SEPARATOR + 246 "</xsl:stylesheet>"; 247 248 final String sourceXml = 249 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR + 250 // "<!DOCTYPE XMLUtils [" + LINE_SEPARATOR + 251 // "<!ELEMENT XMLUtils (test*)>" + LINE_SEPARATOR + 252 // "<!ELEMENT test (valeur*)>" + LINE_SEPARATOR + 253 // "<!ELEMENT valeur (#PCDATA)>" + LINE_SEPARATOR + 254 // "<!ATTLIST valeur attribut CDATA #REQUIRED>]>" + 255 // LINE_SEPARATOR + 256 "<XMLUtils>" + LINE_SEPARATOR + 257 " <test>" + LINE_SEPARATOR + 258 " <valeur attribut=\"Attribut 1\">Valeur 1</valeur>" + LINE_SEPARATOR + 259 " </test>" + LINE_SEPARATOR + 260 " <test>" + LINE_SEPARATOR + 261 " <valeur attribut=\"Attribut 2\">Valeur 2</valeur>" + LINE_SEPARATOR + 262 " </test>" + LINE_SEPARATOR + 263 "</XMLUtils>"; 264 265 System.out.println("Stylesheet:"); 266 System.out.println("============================="); 267 System.out.println(xsl); 268 System.out.println(); 269 270 System.out.println("Source before transformation:"); 271 System.out.println("============================="); 272 System.out.println(sourceXml); 273 System.out.println(); 274 275 // transform to DOM result 276 TransformerFactory tf = TransformerFactory.newInstance(); 277 Transformer t = tf.newTransformer(new StreamSource(new ByteArrayInputStream(xsl.getBytes()))); 278 DOMResult result = new DOMResult(); 279 t.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), result); 280 Document document = (Document)result.getNode(); 281 282 System.out.println("Result after transformation:"); 283 System.out.println("============================"); 284 OutputFormat format = new OutputFormat(); 285 format.setIndenting(true); 286 new XMLSerializer(System.out, format).serialize(document); 287 System.out.println(); 288 289 System.out.println("Node content for element valeur2:"); 290 System.out.println("================================="); 291 NodeList nodes = document.getElementsByTagName("valeur2"); 292 for (int i = 0; i < nodes.getLength(); i++) { 293 Node node = nodes.item(i); 294 System.out.println(" Node value: " + node.getFirstChild().getNodeValue()); 295 System.out.println(" Node attribute: " + node.getAttributes().item(0).getNodeValue()); 296 297 AssertJUnit.assertEquals("Node value mismatch", "Valeur " + (i + 1), node.getFirstChild().getNodeValue()); 298 AssertJUnit.assertEquals("Node attribute mismatch", "Attribut " + (i + 1), node.getAttributes().item(0).getNodeValue()); 299 } 300 } 301 302 /* 303 * @bug 6305029 304 * @summary Test for JDK-6305029 305 */ 306 @Test 307 public final void testBug6305029() throws TransformerException { 308 final String XML_DOCUMENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<prefix:localName xmlns:prefix=\"namespaceUri\"/>"; 309 310 // test SAXSource 311 SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource()); 312 StringWriter resultWriter = new StringWriter(); 313 TransformerFactory tf = TransformerFactory.newInstance(); 314 tf.newTransformer().transform(saxSource, new StreamResult(resultWriter)); 315 AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString()); 316 317 // test StreamSource 318 StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); 319 resultWriter = new StringWriter(); 320 tf.newTransformer().transform(streamSource, new StreamResult(resultWriter)); 321 AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString()); 322 } 323 324 /* 325 * @bug 6505031 326 * @summary Test transformer parses keys and their values coming from different xml documents. 327 */ 328 @Test 329 public final void testBug6505031() throws TransformerException { 330 TransformerFactory tf = TransformerFactory.newInstance(); 331 Transformer t = tf.newTransformer(new StreamSource(getClass().getResource("transform.xsl").toString())); 332 t.setParameter("config", getClass().getResource("config.xml").toString()); 333 t.setParameter("mapsFile", getClass().getResource("maps.xml").toString()); 334 StringWriter sw = new StringWriter(); 335 t.transform(new StreamSource(getClass().getResource("template.xml").toString()), new StreamResult(sw)); 336 String s = sw.toString(); 337 Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); 338 } 339 340 public static class Test8169631And8172974 extends TestTemplate { 341 private final static String xsl = 342 "<?xml version=\"1.0\"?>" + LINE_SEPARATOR + 343 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR + 344 " <xsl:template match=\"/\">" + LINE_SEPARATOR + 345 " <xsl:variable name=\"Counter\" select=\"count(//row)\"/>" + LINE_SEPARATOR + 346 " <xsl:variable name=\"AttribCounter\" select=\"count(//@attrib)\"/>" + LINE_SEPARATOR + 347 " <Counter><xsl:value-of select=\"$Counter\"/></Counter>" + LINE_SEPARATOR + 348 " <AttribCounter><xsl:value-of select=\"$AttribCounter\"/></AttribCounter>" + LINE_SEPARATOR + 349 " </xsl:template>" + LINE_SEPARATOR + 350 "</xsl:stylesheet>" + LINE_SEPARATOR; 351 352 private final static String sourceXml = 353 "<?xml version=\"1.0\"?>" + LINE_SEPARATOR + 354 "<envelope xmlns=\"http://www.sap.com/myns\" xmlns:sap=\"http://www.sap.com/myns\">" + LINE_SEPARATOR + 355 " <sap:row sap:attrib=\"a\">1</sap:row>" + LINE_SEPARATOR + 356 " <row attrib=\"b\">2</row>" + LINE_SEPARATOR + 357 " <row sap:attrib=\"c\">3</row>" + LINE_SEPARATOR + 358 "</envelope>" + LINE_SEPARATOR; 359 360 /** 361 * Utility method to print out transformation result and check values. 362 * 363 * @param type 364 * Text describing type of transformation 365 * @param result 366 * Resulting output of transformation 367 * @param elementCount 368 * Counter of elements to check 369 * @param attribCount 370 * Counter of attributes to check 371 */ 372 private void verifyResult(String type, String result, int elementCount, 373 int attribCount) 374 { 375 printSnippet("Result of transformation from " + type + ":", 376 result); 377 Assert.assertEquals( 378 result.contains("<Counter>" + elementCount + "</Counter>"), 379 true, "Result of transformation from " + type + 380 " should have count of " + elementCount + " elements."); 381 Assert.assertEquals( 382 result.contains("<AttribCounter>" + attribCount + 383 "</AttribCounter>"), true, "Result of transformation from " + 384 type + " should have count of "+ attribCount + " attributes."); 385 } 386 387 // utility to obtain Transformer from TransformerFactory 388 private static Transformer getTransformer(TransformerFactory tf) 389 throws TransformerConfigurationException 390 { 391 return tf.newTransformer( 392 new StreamSource(new ByteArrayInputStream(xsl.getBytes())) 393 ); 394 } 395 396 // utility to obtain Templates from TransformerFactory 397 private static Templates getTemplates(TransformerFactory tf) 398 throws TransformerConfigurationException 399 { 400 return tf.newTemplates( 401 new StreamSource(new ByteArrayInputStream(xsl.getBytes())) 402 ); 403 } 404 405 // utility to construct StreamSource 406 private static StreamSource getStreamSource() { 407 return new StreamSource( 408 new ByteArrayInputStream(sourceXml.getBytes()) 409 ); 410 } 411 412 // utility to construct DOMSource from DocumentBuilderFactory 413 private static DOMSource getDOMSource(DocumentBuilderFactory dbf) 414 throws SAXException, IOException, ParserConfigurationException 415 { 416 return new DOMSource( 417 dbf.newDocumentBuilder().parse( 418 new InputSource( 419 new ByteArrayInputStream(sourceXml.getBytes()) 420 ) 421 ) 422 ); 423 } 424 425 // utility to construct SAXSource from SAXParserFactory 426 private static SAXSource getSAXSource(SAXParserFactory spf) 427 throws SAXException, ParserConfigurationException 428 { 429 return new SAXSource( 430 spf.newSAXParser().getXMLReader(), 431 new InputSource(new ByteArrayInputStream(sourceXml.getBytes())) 432 ); 433 } 434 435 // utility to construct StAXSource from XMLInputFactory 436 private static StAXSource getStAXSource(XMLInputFactory xif) 437 throws XMLStreamException 438 { 439 return new StAXSource( 440 xif.createXMLStreamReader(new StringReader(sourceXml)) 441 ); 442 } 443 444 @DataProvider(name = "testmatrix") 445 public static Object[][] documentTestData() 446 throws TransformerConfigurationException, SAXException, IOException, 447 ParserConfigurationException, XMLStreamException 448 { 449 // get Transformers 450 TransformerFactory tf = TransformerFactory.newInstance(); 451 Transformer t = getTransformer(tf); 452 Transformer tFromTemplates = getTemplates(tf).newTransformer(); 453 454 // get DOMSource objects 455 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 456 DOMSource domSourceWithoutNS = getDOMSource(dbf); 457 dbf.setNamespaceAware(true); 458 DOMSource domSourceWithNS = getDOMSource(dbf); 459 460 // get SAXSource objects 461 SAXParserFactory spf = SAXParserFactory.newInstance(); 462 SAXSource saxSourceWithoutNS = getSAXSource(spf); 463 spf.setNamespaceAware(true); 464 SAXSource saxSourceWithNS = getSAXSource(spf); 465 466 // get StAXSource objects 467 XMLInputFactory xif = XMLInputFactory.newInstance(); 468 StAXSource staxSourceWithNS = getStAXSource(xif); 469 xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false); 470 StAXSource staxSourceWithoutNS = getStAXSource(xif); 471 472 // print XML/XSL snippets to ease understanding of result 473 printSnippet("Source:", sourceXml); 474 printSnippet("Stylesheet:", xsl); 475 476 return new Object[][] { 477 // test StreamSource input with all transformers 478 // namespace awareness is set by transformer 479 {t, getStreamSource(), "StreamSource with namespace support", 0, 1}, 480 {tFromTemplates, getStreamSource(), "StreamSource with namespace support using templates", 0, 1}, 481 // now test DOMSource, SAXSource and StAXSource 482 // with rotating use of created transformers 483 // namespace awareness is set by source objects 484 {t, domSourceWithNS, "DOMSource with namespace support", 0, 1}, 485 {t, domSourceWithoutNS, "DOMSource without namespace support", 3, 3}, 486 {tFromTemplates, saxSourceWithNS, "SAXSource with namespace support", 0, 1}, 487 {tFromTemplates, saxSourceWithoutNS, "SAXSource without namespace support", 3, 3}, 488 {t, staxSourceWithNS, "StAXSource with namespace support", 0, 1}, 489 {t, staxSourceWithoutNS, "StAXSource without namespace support", 3, 3} 490 }; 491 } 492 493 /* 494 * @bug 8169631 8172974 495 * @summary Test combinations of namespace awareness settings on 496 * XSL transformations 497 */ 498 @Test(dataProvider = "testmatrix") 499 public void run(Transformer t, Source s, String label, int elementcount, int attributecount) 500 throws TransformerException 501 { 502 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 503 t.transform(s, new StreamResult(baos)); 504 verifyResult(label, baos.toString(), elementcount, attributecount); 505 } 506 } 507 508 /* 509 * @bug 8150704 510 * @summary Test that XSL transformation with lots of temporary result 511 * trees will not run out of DTM IDs. 512 */ 513 @Test 514 public final void testBug8150704() throws TransformerException, IOException { 515 System.out.println("Testing transformation of Bug8150704-1.xml..."); 516 TransformerFactory tf = TransformerFactory.newInstance(); 517 Transformer t = tf.newTransformer(new StreamSource(getClass().getResource("Bug8150704-1.xsl").toString())); 518 StringWriter sw = new StringWriter(); 519 t.transform(new StreamSource(getClass().getResource("Bug8150704-1.xml").toString()), new StreamResult(sw)); 520 String resultstring = sw.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); 521 String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath())); 522 Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference"); 523 System.out.println("Passed."); 524 525 System.out.println("Testing transformation of Bug8150704-2.xml..."); 526 t = tf.newTransformer(new StreamSource(getClass().getResource("Bug8150704-2.xsl").toString())); 527 sw = new StringWriter(); 528 t.transform(new StreamSource(getClass().getResource("Bug8150704-2.xml").toString()), new StreamResult(sw)); 529 resultstring = sw.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); 530 reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath())); 531 Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); 532 System.out.println("Passed."); 533 } 534 535 private static class Test8162598 extends TestTemplate { 536 private static final String xsl = 537 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LINE_SEPARATOR + 538 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR + 539 " <xsl:template match=\"/\">" + LINE_SEPARATOR + 540 " <root xmlns=\"ns1\">" + LINE_SEPARATOR + 541 " <xsl:call-template name=\"transform\"/>" + LINE_SEPARATOR + 542 " </root>" + LINE_SEPARATOR + 543 " </xsl:template>" + LINE_SEPARATOR + 544 " <xsl:template name=\"transform\">" + LINE_SEPARATOR + 545 " <test1 xmlns=\"ns2\"><b xmlns=\"ns2\"><c xmlns=\"\"></c></b></test1>" + LINE_SEPARATOR + 546 " <test2 xmlns=\"ns1\"><b xmlns=\"ns2\"><c xmlns=\"\"></c></b></test2>" + LINE_SEPARATOR + 547 " <test3><b><c xmlns=\"\"></c></b></test3>" + LINE_SEPARATOR + 548 " <test4 xmlns=\"\"><b><c xmlns=\"\"></c></b></test4>" + LINE_SEPARATOR + 549 " <test5 xmlns=\"ns1\"><b><c xmlns=\"\"></c></b></test5>" + LINE_SEPARATOR + 550 " <test6 xmlns=\"\"/>" + LINE_SEPARATOR + 551 " </xsl:template>" + LINE_SEPARATOR + 552 "</xsl:stylesheet>"; 553 554 private static final String sourceXml = 555 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aaa></aaa>" + LINE_SEPARATOR; 556 /** 557 * Utility method for testBug8162598(). 558 * Provides a convenient way to check/assert the expected namespaces 559 * of a Node and its siblings. 560 * 561 * @param test 562 * The node to check 563 * @param nstest 564 * Expected namespace of the node 565 * @param nsb 566 * Expected namespace of the first sibling 567 * @param nsc 568 * Expected namespace of the first sibling of the first sibling 569 */ 570 571 private void checkNodeNS(Node test, String nstest, String nsb, String nsc) { 572 String testNodeName = test.getNodeName(); 573 if (nstest == null) { 574 Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName); 575 } else { 576 Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName); 577 } 578 Node b = test.getChildNodes().item(0); 579 if (nsb == null) { 580 Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b"); 581 } else { 582 Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b"); 583 } 584 Node c = b.getChildNodes().item(0); 585 if (nsc == null) { 586 Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c"); 587 } else { 588 Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c"); 589 } 590 } 591 592 public void run() throws IOException, TransformerException { 593 printSnippet("Source:", sourceXml); 594 595 printSnippet("Stylesheet:", xsl); 596 597 // transform to DOM result 598 TransformerFactory tf = TransformerFactory.newInstance(); 599 ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes()); 600 Transformer t = tf.newTransformer(new StreamSource(bais)); 601 DOMResult result = new DOMResult(); 602 bais = new ByteArrayInputStream(sourceXml.getBytes()); 603 t.transform(new StreamSource(bais), result); 604 Document document = (Document)result.getNode(); 605 606 System.out.println("Result after transformation:"); 607 System.out.println("============================"); 608 OutputFormat format = new OutputFormat(); 609 format.setIndenting(true); 610 new XMLSerializer(System.out, format).serialize(document); 611 System.out.println(); 612 613 checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null); 614 checkNodeNS(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null); 615 checkNodeNS(document.getElementsByTagName("test3").item(0), null, null, null); 616 checkNodeNS(document.getElementsByTagName("test4").item(0), null, null, null); 617 checkNodeNS(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null); 618 Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(), 619 "unexpected namespace for test6"); 620 } 621 } 622 623 /* 624 * @bug 8162598 625 * @summary Test XSLTC handling of namespaces, especially empty namespace 626 * definitions to reset the default namespace 627 */ 628 @Test 629 public final void testBug8162598() throws IOException, 630 TransformerException 631 { 632 new Test8162598().run(); 633 } 634 635 /** 636 * @bug 8169112 637 * @summary Test compilation of large xsl file with outlining. 638 * 639 * This test merely compiles a large xsl file and tests if its bytecode 640 * passes verification by invoking the transform() method for 641 * dummy content. The test succeeds if no Exception is thrown 642 */ 643 @Test 644 public final void testBug8169112() throws FileNotFoundException, 645 TransformerException 646 { 647 TransformerFactory tf = TransformerFactory.newInstance(); 648 String xslFile = getClass().getResource("Bug8169112.xsl").toString(); 649 Transformer t = tf.newTransformer(new StreamSource(xslFile)); 650 String xmlIn = "<?xml version=\"1.0\"?><DOCROOT/>"; 651 ByteArrayInputStream bis = new ByteArrayInputStream(xmlIn.getBytes()); 652 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 653 t.transform(new StreamSource(bis), new StreamResult(bos)); 654 } 655 656 /** 657 * @bug 8169772 658 * @summary Test transformation of DOM with null valued text node 659 * 660 * This test would throw a NullPointerException during transform when the 661 * fix was not present. 662 */ 663 @Test 664 public final void testBug8169772() throws ParserConfigurationException, 665 SAXException, IOException, TransformerException 666 { 667 // create a small DOM 668 Document doc = DocumentBuilderFactory.newInstance(). 669 newDocumentBuilder().parse( 670 new ByteArrayInputStream( 671 "<?xml version=\"1.0\"?><DOCROOT/>".getBytes() 672 ) 673 ); 674 675 // insert a bad element 676 Element e = doc.createElement("ERROR"); 677 e.appendChild(doc.createTextNode(null)); 678 doc.getDocumentElement().appendChild(e); 679 680 // transform 681 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 682 TransformerFactory.newInstance().newTransformer().transform( 683 new DOMSource(doc.getDocumentElement()), new StreamResult(bos) 684 ); 685 System.out.println("Transformation result (DOM with null text node):"); 686 System.out.println("================================================"); 687 System.out.println(bos); 688 } 689 }