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 }