1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package org.apache.qetest.trax; 21 22 import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory; 23 import com.sun.org.apache.xml.internal.serializer.Serializer; 24 import com.sun.org.apache.xml.internal.serializer.SerializerFactory; 25 import java.io.BufferedInputStream; 26 import java.io.BufferedReader; 27 import java.io.File; 28 import java.io.FileInputStream; 29 import java.io.FileOutputStream; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.InputStreamReader; 33 import java.io.Reader; 34 import java.util.Properties; 35 import javax.xml.parsers.DocumentBuilder; 36 import javax.xml.parsers.DocumentBuilderFactory; 37 import javax.xml.parsers.ParserConfigurationException; 38 import javax.xml.parsers.SAXParser; 39 import javax.xml.parsers.SAXParserFactory; 40 import javax.xml.transform.OutputKeys; 41 import javax.xml.transform.Result; 42 import javax.xml.transform.Templates; 43 import javax.xml.transform.Transformer; 44 import javax.xml.transform.TransformerConfigurationException; 45 import javax.xml.transform.TransformerException; 46 import javax.xml.transform.TransformerFactory; 47 import javax.xml.transform.dom.DOMResult; 48 import javax.xml.transform.dom.DOMSource; 49 import javax.xml.transform.sax.SAXResult; 50 import javax.xml.transform.sax.SAXSource; 51 import javax.xml.transform.sax.SAXTransformerFactory; 52 import javax.xml.transform.sax.TransformerHandler; 53 import javax.xml.transform.stream.StreamResult; 54 import javax.xml.transform.stream.StreamSource; 55 import jaxp.library.JAXPFileBaseTest; 56 import static jaxp.library.JAXPTestUtilities.compareWithGold; 57 import static jaxp.library.JAXPTestUtilities.filenameToURL; 58 import static org.apache.qetest.trax.TraxConst.GOLDEN_DIR; 59 import static org.apache.qetest.trax.TraxConst.XML_DIR; 60 import static jaxp.library.JAXPTestUtilities.getNextFile; 61 import static org.testng.Assert.*; 62 import org.testng.annotations.Test; 63 import org.w3c.dom.Node; 64 import org.xml.sax.InputSource; 65 import org.xml.sax.SAXException; 66 import org.xml.sax.XMLFilter; 67 import org.xml.sax.XMLReader; 68 69 /** 70 * Test version of xml-xalan/java/samples/trax/Examples.java. 71 * This file is essentially copied from the Examples for TRAX, or 72 * javax.xml.transform; however this file actually validates most output and 73 * behavior for correctness. 74 */ 75 public class ExamplesTest extends JAXPFileBaseTest { 76 /** 77 * Test XML file 1 name. 78 */ 79 private static final String SOURCE_ID = XML_DIR + "xml/foo.xml"; 80 81 /** 82 * Test XML file 2 name. 83 */ 84 private static final String SOURCE_ID2 = XML_DIR + "xml/baz.xml"; 85 86 /** 87 * Test stylesheet file name. 88 */ 89 private static final String XSL_ID = XML_DIR + "xsl/foo.xsl"; 90 91 /** 92 * Show the Transformer as a simple XMLFilter. This is pretty similar to 93 * exampleXMLReader, except that here the parent XMLReader is created by the 94 * caller, instead of automatically within the XMLFilter. This gives the 95 * caller more direct control over the parent reader. 96 * 97 * @throws ParserConfigurationException if the implementation is not 98 * available or cannot be instantiated. 99 * @throws SAXException for SAX error. 100 * @throws IOException if any I/O operation error. 101 * @throws TransformerConfigurationException Thrown in case of 102 * ServiceConfigurationError service configuration error or if the 103 * implementation is not available or cannot be instantiated. 104 */ 105 @Test 106 public void exampleXMLFilter() throws IOException, SAXException, 107 ParserConfigurationException, TransformerConfigurationException { 108 String outputFile = getNextFile(this.getClass()); 109 try (FileOutputStream fos = new FileOutputStream(outputFile)) { 110 111 TransformerFactory tfactory = TransformerFactory.newInstance(); 112 SAXParserFactory factory = SAXParserFactory.newInstance(); 113 factory.setNamespaceAware(true); 114 SAXParser jaxpParser = factory.newSAXParser(); 115 XMLReader reader = jaxpParser.getXMLReader(); 116 117 // Set the result handling to be a serialization to the file output stream. 118 Serializer serializer = SerializerFactory.getSerializer( 119 OutputPropertiesFactory.getDefaultMethodProperties("xml")); 120 serializer.setOutputStream(fos); 121 reader.setContentHandler(serializer.asContentHandler()); 122 reader.setFeature("http://xml.org/sax/features/namespace-prefixes", 123 true); 124 reader.setFeature("http://apache.org/xml/features/validation/dynamic", 125 true); 126 XMLFilter filter = ((SAXTransformerFactory) tfactory) 127 .newXMLFilter(new StreamSource(filenameToURL(XSL_ID))); 128 filter.setParent(reader); 129 130 // Now, when you call transformer.parse, it will set itself as 131 // the content handler for the parser object (it's "parent"), and 132 // will then call the parse method on the parser. 133 filter.parse(new InputSource(filenameToURL(SOURCE_ID))); 134 } 135 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_14.out", outputFile)); 136 } 137 138 /** 139 * Show simple transformation from reader to output stream. In general this 140 * use case is discouraged, since the XML encoding can not be processed. 141 * 142 * @throws IOException if any I/O operation error. 143 * @throws TransformerException If an unrecoverable error occurs during the 144 * course of the transformation. 145 */ 146 @Test 147 public void exampleFromReader() throws IOException, TransformerException { 148 String outputFile = getNextFile(this.getClass()); 149 // Create a transform factory instance. 150 TransformerFactory tfactory = TransformerFactory.newInstance(); 151 152 // Note that in this case the XML encoding can not be processed! 153 Reader xslReader = new BufferedReader(new InputStreamReader(new FileInputStream(XSL_ID), "UTF-8")); 154 StreamSource xslSource = new StreamSource(xslReader); 155 // Note that if we don't do this, relative URLs can not be resolved correctly! 156 xslSource.setSystemId(filenameToURL(XSL_ID)); 157 158 // Create a transformer for the stylesheet. 159 Transformer transformer = tfactory.newTransformer(xslSource); 160 161 Reader xmlReader = new BufferedReader(new InputStreamReader(new FileInputStream(SOURCE_ID), "UTF-8")); 162 StreamSource xmlSource = new StreamSource(xmlReader); 163 // Note that if we don't do this, relative URLs can not be resolved correctly! 164 xmlSource.setSystemId(filenameToURL(SOURCE_ID)); 165 166 // Transform the source XML to output file. 167 transformer.transform(xmlSource, new StreamResult(outputFile)); 168 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_5.out", outputFile)); 169 } 170 171 /** 172 * Show the Transformer using SAX events in and SAX events out. 173 * 174 * @throws ParserConfigurationException if the implementation is not 175 * available or cannot be instantiated. 176 * @throws SAXException for SAX error. 177 * @throws IOException if any I/O operation error. 178 * @throws TransformerException If an unrecoverable error occurs during the 179 * course of the transformation. 180 */ 181 @Test 182 public void exampleContentHandlerToContentHandler() 183 throws TransformerException, IOException, SAXException, ParserConfigurationException { 184 TransformerFactory tfactory = TransformerFactory.newInstance(); 185 String outputFile = getNextFile(this.getClass()); 186 try (FileOutputStream fos = new FileOutputStream(outputFile)) { 187 // Does this factory support SAX features? 188 if (!tfactory.getFeature(SAXSource.FEATURE)) { 189 return; 190 } 191 // If so, we can safely cast. 192 SAXTransformerFactory stfactory = (SAXTransformerFactory) tfactory; 193 194 // A TransformerHandler is a ContentHandler that will listen for 195 // SAX events, and transform them to the result. 196 TransformerHandler handler 197 = stfactory.newTransformerHandler(new StreamSource(filenameToURL(XSL_ID))); 198 199 // Set the result handling to be a serialization to the file output stream. 200 Serializer serializer = SerializerFactory.getSerializer( 201 OutputPropertiesFactory.getDefaultMethodProperties("xml")); 202 serializer.setOutputStream(fos); 203 Result result = new SAXResult(serializer.asContentHandler()); 204 205 handler.setResult(result); 206 SAXParserFactory factory = SAXParserFactory.newInstance(); 207 factory.setNamespaceAware(true); 208 XMLReader reader = factory.newSAXParser().getXMLReader(); 209 reader.setContentHandler(handler); 210 211 // It's a good idea for the parser to send lexical events. 212 // The TransformerHandler is also a LexicalHandler. 213 reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); 214 215 // Parse the source XML, and send the parse events to the TransformerHandler. 216 reader.parse(filenameToURL(SOURCE_ID)); 217 } 218 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_3.out", outputFile)); 219 } 220 221 /** 222 * Show the Transformer using SAX events in and DOM nodes out. 223 * 224 * @throws ParserConfigurationException if the implementation is not 225 * available or cannot be instantiated. 226 * @throws SAXException for SAX error. 227 * @throws IOException if any I/O operation error. 228 * @throws TransformerException If an unrecoverable error occurs during the 229 * course of the transformation. 230 */ 231 @Test 232 public void exampleContentHandler2DOM() 233 throws ParserConfigurationException, TransformerException, 234 SAXException, IOException { 235 String outputFile = getNextFile(this.getClass()); 236 TransformerFactory tfactory = TransformerFactory.newInstance(); 237 238 // Make sure the transformer factory we obtained supports both 239 // DOM and SAX. 240 if (!(tfactory.getFeature(SAXSource.FEATURE) 241 && tfactory.getFeature(DOMSource.FEATURE))) { 242 return; 243 } 244 // We can now safely cast to a SAXTransformerFactory. 245 SAXTransformerFactory sfactory = (SAXTransformerFactory) tfactory; 246 247 // Create an Document node as the root for the output. 248 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 249 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 250 org.w3c.dom.Document outNode = docBuilder.newDocument(); 251 252 // Create a ContentHandler that can liston to SAX events 253 // and transform the output to DOM nodes. 254 TransformerHandler handler 255 = sfactory.newTransformerHandler(new StreamSource(filenameToURL(XSL_ID))); 256 handler.setResult(new DOMResult(outNode)); 257 258 SAXParserFactory factory = SAXParserFactory.newInstance(); 259 factory.setNamespaceAware(true); 260 XMLReader reader = factory.newSAXParser().getXMLReader(); 261 reader.setContentHandler(handler); 262 reader.setProperty("http://xml.org/sax/properties/lexical-handler", 263 handler); 264 265 // Send the SAX events from the parser to the transformer, 266 // and thus to the DOM tree. 267 reader.parse(filenameToURL(SOURCE_ID)); 268 269 // Serialize the node for diagnosis. 270 // This serializes to outNames.nextName() 271 Transformer serializer = tfactory.newTransformer(); 272 serializer.setOutputProperty(OutputKeys.INDENT, "yes"); 273 serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 274 serializer.transform(new DOMSource(outNode), 275 new StreamResult(outputFile)); 276 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_2.out", outputFile)); 277 } 278 279 /** 280 * A fuller example showing how the TrAX interface can be used to serialize 281 * a DOM tree. 282 * 283 * @throws ParserConfigurationException if the implementation is not 284 * available or cannot be instantiated. 285 * @throws SAXException for SAX error. 286 * @throws IOException if any I/O operation error. 287 * @throws TransformerException If an unrecoverable error occurs during the 288 * course of the transformation. 289 */ 290 @Test 291 public void exampleAsSerializer() 292 throws ParserConfigurationException, SAXException, IOException, TransformerException { 293 String outputFile = getNextFile(this.getClass()); 294 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 295 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 296 org.w3c.dom.Document outNode = docBuilder.newDocument(); 297 Node doc = docBuilder.parse(new InputSource(filenameToURL(SOURCE_ID))); 298 299 TransformerFactory tfactory = TransformerFactory.newInstance(); 300 301 // This creates a transformer that does a simple identity transform, 302 // and thus can be used for all intents and purposes as a serializer. 303 Transformer serializer = tfactory.newTransformer(); 304 305 Properties oprops = new Properties(); 306 oprops.put("method", "html"); 307 oprops.put("{http://xml.apache.org/xslt}indent-amount", "2"); 308 serializer.setOutputProperties(oprops); 309 serializer.transform(new DOMSource(doc), 310 new StreamResult(outputFile)); 311 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_1.out", outputFile)); 312 } 313 314 /** 315 * Show simple transformation from input stream to output stream. 316 * 317 * @throws IOException if any I/O operation error. 318 * @throws TransformerException If an unrecoverable error occurs during the 319 * course of the transformation. 320 */ 321 @Test 322 public void exampleFromStream() throws IOException, TransformerException { 323 String outputFile = getNextFile(this.getClass()); 324 try (InputStream xslIS = new BufferedInputStream(new FileInputStream(XSL_ID)); 325 InputStream xmlIS = new BufferedInputStream(new FileInputStream(SOURCE_ID))) { 326 // Create a transform factory instance. 327 TransformerFactory tfactory = TransformerFactory.newInstance(); 328 StreamSource xslSource = new StreamSource(xslIS); 329 // Note that if we don't do this, relative URLs can not be resolved correctly! 330 xslSource.setSystemId(filenameToURL(XSL_ID)); 331 332 // Create a transformer for the stylesheet. 333 Transformer transformer = tfactory.newTransformer(xslSource); 334 StreamSource xmlSource = new StreamSource(xmlIS); 335 // Note that if we don't do this, relative URLs can not be resolved correctly! 336 xmlSource.setSystemId(filenameToURL(SOURCE_ID)); 337 338 // Transform the source XML to output file. 339 transformer.transform(xmlSource, new StreamResult(outputFile)); 340 } 341 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_6.out", outputFile)); 342 } 343 344 /** 345 * Show how to override output properties. 346 * 347 * @throws IOException if any I/O operation error. 348 * @throws TransformerException If an unrecoverable error occurs during the 349 * course of the transformation. 350 */ 351 @Test 352 public void exampleOutputProperties() 353 throws IOException, TransformerException { 354 String outputFile = getNextFile(this.getClass()); 355 356 TransformerFactory tfactory = TransformerFactory.newInstance(); 357 Templates templates = tfactory.newTemplates(new StreamSource(filenameToURL(XSL_ID))); 358 Properties oprops = templates.getOutputProperties(); 359 360 oprops.put(OutputKeys.INDENT, "yes"); 361 362 Transformer transformer = templates.newTransformer(); 363 364 transformer.setOutputProperties(oprops); 365 transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)), 366 new StreamResult(outputFile)); 367 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_7.out", outputFile)); 368 } 369 370 /** 371 * Show how to transform a DOM tree into another DOM tree. This uses the 372 * javax.xml.parsers to parse an XML file into a DOM, and create an output 373 * DOM. 374 * 375 * @throws ParserConfigurationException if the implementation is not 376 * available or cannot be instantiated. 377 * @throws SAXException for SAX error. 378 * @throws IOException if any I/O operation error. 379 * @throws TransformerException If an unrecoverable error occurs during the 380 * course of the transformation. 381 */ 382 public void exampleDOM2DOM() throws IOException, SAXException, 383 TransformerException, ParserConfigurationException { 384 String outputFile = getNextFile(this.getClass()); 385 TransformerFactory tfactory = TransformerFactory.newInstance(); 386 387 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 388 dfactory.setNamespaceAware(true); 389 DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); 390 org.w3c.dom.Document outNode = docBuilder.newDocument(); 391 Node xslDoc = docBuilder.parse(new InputSource(filenameToURL(XSL_ID))); 392 DOMSource dsource = new DOMSource(xslDoc); 393 // If we don't do this, the transformer won't know how to 394 // resolve relative URLs in the stylesheet. 395 dsource.setSystemId(filenameToURL(XSL_ID)); 396 397 Templates templates = tfactory.newTemplates(dsource); 398 399 Transformer transformer = templates.newTransformer(); 400 Node xmlDoc = docBuilder.parse(new InputSource(filenameToURL(SOURCE_ID))); 401 402 transformer.transform(new DOMSource(xmlDoc), new DOMResult(outNode)); 403 404 Transformer serializer = tfactory.newTransformer(); 405 serializer.transform(new DOMSource(outNode), new StreamResult(outputFile)); 406 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_4.out", outputFile)); 407 } 408 409 /** 410 * Show the Transformer using SAX events in and DOM nodes out. 411 * 412 * @throws IOException if any I/O operation error. 413 * @throws TransformerException If an unrecoverable error occurs during the 414 * course of the transformation. 415 */ 416 @Test 417 public void exampleSimple1() 418 throws IOException, TransformerException { 419 String outputFile = getNextFile(this.getClass()); 420 // Create a transform factory instance. 421 TransformerFactory tfactory = TransformerFactory.newInstance(); 422 423 // Create a transformer for the stylesheet. 424 Transformer transformer 425 = tfactory.newTransformer(new StreamSource(filenameToURL(XSL_ID))); 426 // No need to setSystemId, the transformer can get it from the URL 427 428 transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)), 429 new StreamResult(outputFile)); 430 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_8.out", outputFile)); 431 } 432 433 /** 434 * Show the simplest possible transformation from File to a File. 435 * 436 * @throws IOException if any I/O operation error. 437 * @throws TransformerException If an unrecoverable error occurs during the 438 * course of the transformation. 439 */ 440 @Test 441 public void exampleSimple2() 442 throws IOException, TransformerException { 443 String outputFile = getNextFile(this.getClass()); 444 445 TransformerFactory tfactory = TransformerFactory.newInstance(); 446 447 // Create a transformer for the stylesheet. 448 Transformer transformer 449 = tfactory.newTransformer(new StreamSource(new File(XSL_ID))); 450 // No need to setSystemId, the transformer can get it from the File 451 452 transformer.transform(new StreamSource(new File(SOURCE_ID)), 453 new StreamResult(new File(outputFile))); 454 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_9.out", outputFile)); 455 } 456 457 /** 458 * Show the that a transformer can be reused, and show resetting a parameter 459 * on the transformer. 460 * 461 * @throws IOException if any I/O operation error. 462 * @throws TransformerException If an unrecoverable error occurs during the 463 * course of the transformation. 464 */ 465 @Test 466 public void exampleTransformerReuse() 467 throws IOException, TransformerException { 468 String outputFile = getNextFile(this.getClass()); 469 // Create a transform factory instance. 470 TransformerFactory tfactory = TransformerFactory.newInstance(); 471 472 // Create a transformer for the stylesheet. 473 Transformer transformer 474 = tfactory.newTransformer(new StreamSource(filenameToURL(XSL_ID))); 475 476 transformer.setParameter("a-param", "hello to you!"); 477 478 transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)), 479 new StreamResult(outputFile)); 480 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_10.out", outputFile)); 481 482 transformer.setParameter("a-param", "hello to me!"); 483 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 484 String outputFile2 = getNextFile(this.getClass()); 485 transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)), 486 new StreamResult(outputFile2)); 487 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_11.out", outputFile)); 488 } 489 490 /** 491 * Show the simplest possible transformation from system id to output 492 * stream. 493 * 494 * @throws IOException if any I/O operation error. 495 * @throws TransformerException If an unrecoverable error occurs during the 496 * course of the transformation. 497 */ 498 @Test 499 public void exampleUseTemplatesObj() throws IOException, TransformerException { 500 String outputFile1 = getNextFile(this.getClass()); 501 String outputFile2 = getNextFile(this.getClass()); 502 TransformerFactory tfactory = TransformerFactory.newInstance(); 503 504 // Create a templates object, which is the processed, 505 // thread-safe representation of the stylesheet. 506 Templates templates = tfactory.newTemplates(new StreamSource(filenameToURL(XSL_ID))); 507 508 // Illustrate the fact that you can make multiple transformers 509 // from the same template. 510 Transformer transformer1 = templates.newTransformer(); 511 Transformer transformer2 = templates.newTransformer(); 512 513 transformer1.transform(new StreamSource(filenameToURL(SOURCE_ID)), 514 new StreamResult(outputFile1)); 515 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_12.out", outputFile1)); 516 517 transformer2.transform(new StreamSource(filenameToURL(SOURCE_ID2)), 518 new StreamResult(outputFile2)); 519 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_13.out", outputFile2)); 520 } 521 522 /** 523 * Show the Transformer as a SAX2 XMLReader. An XMLFilter obtained from 524 * newXMLFilter should act as a transforming XMLReader if setParent is not 525 * called. Internally, an XMLReader is created as the parent for the 526 * XMLFilter. 527 * 528 * @throws SAXException for SAX error. 529 * @throws IOException if any I/O operation error. 530 * @throws TransformerConfigurationException Thrown in case of 531 * ServiceConfigurationError service configuration error or if the 532 * implementation is not available or cannot be instantiated. 533 */ 534 @Test 535 public void exampleXMLReader() throws IOException, SAXException, 536 TransformerConfigurationException { 537 String outputFile = getNextFile(this.getClass()); 538 try (FileOutputStream fos = new FileOutputStream(outputFile)) { 539 TransformerFactory tfactory = TransformerFactory.newInstance(); 540 XMLReader reader = ((SAXTransformerFactory) tfactory) 541 .newXMLFilter(new StreamSource(filenameToURL(XSL_ID))); 542 543 // Set the result handling to be a serialization to the file output stream. 544 Serializer serializer = SerializerFactory.getSerializer(OutputPropertiesFactory.getDefaultMethodProperties("xml")); 545 546 serializer.setOutputStream(fos); 547 548 reader.setContentHandler(serializer.asContentHandler()); 549 reader.parse(new InputSource(filenameToURL(SOURCE_ID))); 550 } 551 assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_15.out", outputFile)); 552 } 553 }