- Introduction
- C++ with MSXML
- Java with JAXP and Xalan
- Conclusion
- For More Information
Java with JAXP and Xalan
The Java example is coded in two source files: DOMAndXSLT.java is the class for the application, and a SAX error-handling class is coded in SAXErrorHandler.java. For this article, I'll assume that you already know the basics of using the DOM with JAXP and I'll just focus on the parts of the program that deal with the XSLT transformation. That code is located in lines 5978 of Listing 5 (DOMAndXSLT.java).
Listing 5 DOMAndXSLT.java
1 /* DOMAndXSLT.java 2 3 This program illustrates basic techniques for transforming 4 a DOM source document into a DOM result document using 5 JAXP and Xalan. 6 7 Michael C. Rawlins, 2003, for InformIT 8 9 */ 10 11 // Standard libraries 12 import java.io.*; 13 14 // XML packages 15 import javax.xml.parsers.*; 16 import javax.xml.transform.*; 17 import javax.xml.transform.dom.*; 18 import org.xml.sax.*; 19 import org.xml.sax.helpers.*; 20 import org.w3c.dom.*; 21 import org.apache.xml.serialize.*; 22 23 public class DOMAndXSLT 24 { 25 26 public static void main (String argv []) 27 { 28 // Local variables 29 Document docSource; 30 Document docResult; 31 Document docXSLT; 32 DOMSource dsSource; 33 DOMSource dsXSLT; 34 DOMResult drResult; 35 OutputFormat MyOutputFormat; 36 XMLSerializer MySerializer; 37 FileOutputStream OutputXML; 38 39 System.out.println("DOM and XSLT Demonstration"); 40 41 try 42 { 43 // Create a document builder factory, the builder, and load 44 // the source document. The factory must be namespace-aware for 45 // XSLT. 46 DocumentBuilderFactory dFactory = 47 DocumentBuilderFactory.newInstance(); 48 dFactory.setNamespaceAware(true); 49 DocumentBuilder dBuilder = dFactory.newDocumentBuilder(); 50 dBuilder.setErrorHandler(new SAXErrorHandler()); 51 52 // Load and parse the source and stylesheet documents 53 docSource = dBuilder.parse(new File("HelloWorld.xml")); 54 docXSLT = dBuilder.parse(new File("HelloWorld.xsl")); 55 56 // Create the result document 57 docResult = dBuilder.newDocument(); 58 59 // Create DOMSource objects for the source document and stylesheet. 60 // Set the base URI for the system ID so that any relative URIs can 61 // be resolved - not needed for this constrained example, but is 62 // good practice. 63 dsSource = new DOMSource(docSource); 64 dsSource.setSystemId("HelloWorld.xml"); 65 dsXSLT = new DOMSource(docXSLT); 66 dsXSLT.setSystemId("HelloWorld.xsl"); 67 68 // Create a DOMResult object for the result of the 69 // transformation, and set its node to be the result Document 70 drResult = new DOMResult(docResult); 71 72 // Create a transformer factory, then a transformer from the 73 // stylesheet DOMSource 74 TransformerFactory tFactory = TransformerFactory.newInstance(); 75 Transformer transformer = tFactory.newTransformer(dsXSLT); 76 77 // Perform the transformation and get the DOM result tree 78 transformer.transform(dsSource, drResult); 79 80 // Save Output XML Document by creating an output stream, an 81 // XMLSerializer, assigning the output stream to the serializer, and 82 // setting the serializer to be a DOM serializer 83 OutputXML = new FileOutputStream("Result.xml"); 84 MySerializer = new XMLSerializer(); 85 MySerializer.setOutputByteStream(OutputXML); 86 MySerializer.asDOMSerializer(); 87 88 // Create the Output Format for the Serializer for 89 // XML, UTF-8, and indentation true 90 MyOutputFormat = new OutputFormat("XML","UTF-8",true); 91 MySerializer.setOutputFormat(MyOutputFormat); 92 93 // Write out the document, and close the output stream 94 MySerializer.serialize(docResult); 95 OutputXML.flush(); 96 OutputXML.close(); 97 } 98 99 // General purpose catch block 100 catch (Throwable t) 101 { 102 t.printStackTrace (); 103 System.exit(1); 104 } 105 106 // Finish up 107 System.out.println("Successful Completion"); 108 System.exit(0); 109 } 110 }
While MSXML supports XSLT transformations by extending the DOM Document interface with a new method, JAXP adds an entirely new interface, the "transformer" interface. A transformer object is built from a TransformerFactory in a fashion very similar to the way in which a JAXP DocumentBuilder object is produced from a DocumentBuilderFactory. The actual transformation is again a single method call, the Transformer's transform, but the arguments are the source and result documents, passed as DOMSource and DOMResult objects, respectively. The Transformer object is initialized by passing the XSLT stylesheet, also as a DOMSource object, in the newTransformer call.
As with MSXML, most of the complexity in using XSLT is in setting up for the transformation, and not in the actual method call that performs the transformation. The transform and newTransformer methods don't take DOM Documents as arguments, but instead take DOMSource or DOMResult objects. The source document and stylesheet, after being loaded as DOM Documents, are used to create DOMSource objects. This is performed in lines 5966. Notice that after creating these objects the sample program also calls their setSystemID methods. This method is not needed in our example, but is good programming practice. It's required if either the source or stylesheet document uses relative URLs to reference other XML documents, stylesheets, entities, etc. The setSystemID enables JAXP to locate these other documents. At line 70, the DOMResult document is created from the empty result DOM Document.
Finally, in lines 7275 we create a TransformerFactory and the Transformer object, and then perform the transformation at line 78.
If you're familiar with JAXP, you may notice that this program uses the same DocumentBuilder object to load both the source document and the stylesheet. This approach works fine if you don't need to validate the source document against a DTD or schema. However, if you need to validate, you have to create a validating DocumentBuilder for the source document and a different, non-validating but namespace-aware DocumentBuilder for the stylesheet, as stylesheets aren't normally validated against a schema.