Notes on the javax.xml.transform
package
Jean-François Perrot
- 3 key concepts (interfaces) :
Transformer , Source
, Result
- A Transformer object tr
takes
a Source object src and uses a Result object res
- Creating a Transformer object
- DOM : javax.xml.transform.dom
- Stream : javax.xml.transform.stream
- SAX : javax.xml.transform.sax
- Examples
- Names / marks : From text to HTML
- Menu : XML to PDF
Summary : http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/package-summary.html
-
-
to store the result
of its work, according to the following pattern
Transformer
tr;
Source src;
Result res;
tr.transform(src, res);
N.B. The transform
method operates a side-effect on the Result
object, which must be created before.
This is not a return
in the functional sense.
Each of Source
and Result
objects can be of
3 kinds
: DOM
, Stream
and SAX
,
see below.
The choice of the kind for Source
is independent form the
choice for Result
.
-
is done
via a
TransformerFactory
instance, which in turn is obtained via
TransformerFactory trsf =
TransformerFactory.newInstance();
A TransformerFactory
object creates a Transformer
by
Transformer
tr = trsf.newTransformer();
without an argument : identical transformer, copies its Source
document to its Result
,
albeit with a change of representation if Source
and Result
are not of the same kind.
A typical example is the standard way to write a DOM document to a file.
Source
src_tr;
Transformer tr = trsf.newTransformer(src_tr);
with an argument which is a Source
object containing an
XSLT document :
the transformer then implements the transformation specified by that
document,
together with the change of representation involved by the respective
kinds of src
and res
.
If the document is not a valid XSLT transform, then the newTransformer
method will raise a TransformerConfigurationException
.
-
DOMSource
(class)
A DOMSource
object is readily obtained from a DOM Document
:
Document doc;
Source src = new DOMSource(doc);
Remember that your Document
must be namespace-aware
!
DOMresult
(class)
You have to create an empty instance before having it filled by the
transformer.
Result res = new DOMResult();
tr.transform(src, res);
After which you extract the transformed DOM Document
with
Document tdoc = (Document) res.getNode();
-
Used when your XML
documents are available as files rather than as DOM trees.
Remember that an XML file carries the information about character
encoding,
ant that this info is automatically used, so that we don't have to
worry bout it.
StreamSource
(class)
The most common way to create a StreamSource
object is
from a filename :
String fichIn;
Source src = new StreamSource(new File(fichIn));
StreamResult
(class)
Same here :
String fichOut;
Result res = new StreamSource(new File(fichOut));
or alternatively
Result res = new StreamResult(System.out);
Remember that since we are dealing with XML documents, which carry the
indication of character encoding,
no further menction of file encoding should appear here.
However, a number of additional specifications about the format of the
output file must be given as configuration info
to the Transformer
object (and not to the StreamResult
)
in the form :
tr.setOutputProperty(OutputKeys.PROP_NAME, value);
Some of them are of critical importance !
Example (from One2HtmlT.java
)
:
tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
DTDurl); // print DTD
tr.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, PubID);
tr.setOutputProperty(OutputKeys.INDENT, "yes"); // easy reading
See the JavaDoc of class OutputKeys
for a complete list.
-
Streams provide an
abstract level for files.
The
SAX technology turns XML character files into sequences of
events, which are consumed by ContentHandler
objects.
Such event sequences are seen as a valid way to present XML document to
a transformer (SAXSource
)
and to retrieve a transformed XML document (SAXResult
).
SAXSource
(class)
Built using an XMLReader
(SAX parser) for which the Transformer
object plays the role of a ContentHandler
,
together with an InputSource
to be parsed.
Source don = new SAXSource(parser, new
InputSource(nomFich));
The only reason I imagine to use a SAXSource
instead of a
StreamSource
is that the parser
may be asked to validate the file wrt the DTD.
XMLReader parser = XMLReaderFactory.createXMLReader();
try {
parser.setFeature("http://xml.org/sax/features/validation", true);
parser.setFeature("http://xml.org/sax/features/namespaces", true);
} catch (SAXException e) {
System.err.println("No Validation");
System.exit(7);
}
SaxVerif verif = new SaxVerif();
// an error handler
parseur.setErrorHandler(verif);
Source don = new
SAXSource(parser, new InputSource(nomFich));
... then proceed as
usual ...
SAXResult
(class)
Such a Result
object will feed SAX events to a ContentHandler
provided by the application.
Therefore, creating a SAXResult
requires a ContentHandler
as an argument to the constructor.
A typical example is given by Apache-Fop,
where the XSLT transform generates an XSL-FO file
(written in the Formatting-Objects XML dialect) which is
immediately turned into a PDF file.
Generating the PDF is done by a Fop (Formatting-Object Processor)
object which owns a ContentHandler
.
Here is the code :
Source src_tr = new StreamSource(new
File(fichFst));
Transformer tf =
TransformerFactory.newInstance().newTransformer(src_tr);
Source src = new StreamSource(new File(fichIn));
Result res = new SAXResult(fop.getDefaultHandler()); //
*******
tf.transform(src, res);
In this way the FO-file is is generated "on the fly" and never written
out on disk,
exactly like the HTML file that is produced by an XSLT transform
executed via a processing instruction by a browser.
-
-
reusing the static
method
Document doc1fromText(BufferedReader in)
from class Build1CDfromText
studied in session #1,
and applying one of our examples of XSLT transforms.
Try it out with data file NomsNotes2.txt
!
Program file Text2HTMLT.java
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
public class Text2HTMLT {
public static String url_trsf =
"../NomNoteXSL/tableAtSort.xsl";
public static void main(String[] args) throws
Exception{
String fichIn = args[0];
String fichOut = args[1];
BufferedReader in =
new
BufferedReader (
new InputStreamReader(new FileInputStream (fichIn),
"UTF-8") );
StreamSource src_tr = new
StreamSource(url_trsf);
Transformer trans =
TransformerFactory.newInstance().newTransformer(src_tr);
Source src = new
DOMSource(Build1CDfromText.doc1fromText(in));
Result res = new
StreamResult(
new File (fichOut
));
trans.transform(src, res);
} // main
}//Text2HTMLT
-
Try it out with data
file
Menu.xml !
Program file Menu2PDF.java
.
/* Menu to PDF with Apache-Fop 1.1
*/
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Result;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
public class Menu2PDF {
public static String fichFst = "Menu2FO.xsl"; //
XSLT stylesheet
public static void main(String[] args) throws
Exception{
String fichIn = args[0]; // XML
source
String fichOut = args[1]; // PDF
output
OutputStream out = new
BufferedOutputStream(new FileOutputStream(new File(fichOut)));
Fop fop =
FopFactory.newInstance().newFop(MimeConstants.MIME_PDF, out);
try {
Source
src_tr = new StreamSource(new File(fichFst));
Transformer tf =
TransformerFactory.newInstance().newTransformer(src_tr);
Source
src = new StreamSource(new File(fichIn));
Result
res = new SAXResult(fop.getDefaultHandler()); // hic jacet lepus
tf.transform(src, res);
} catch (Exception e) {
System.out.println("Erreur "+ e.getMessage());
}finally{
out.close();
}
} // main
}//Menu2PDF