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