Java : TransformerFactory (XML) - API使用例
TransformerFactory (Java SE 17 & JDK 17) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
TransformerFactoryは、XMLオブジェクト(DOMやSAX、StAX)を、XML形式の文字列やファイルに変換するための起点となるクラスです。
(正確には、DOMからSAXなどへの変換も可能です)
汎用APIなので、DOMやSAX、StAXに依存していません。
DOMからXML形式の文字列へ変換する一連の流れは次のようになります。
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.newDocument();
final var root = document.createElement("root");
document.appendChild(root);
final var text = document.createTextNode("abcd");
root.appendChild(text);
final var transformerFactory = TransformerFactory.newInstance();
final var transformer = transformerFactory.newTransformer();
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<?xml version="1.0" encoding="UTF-8" standalone="no"?><root>abcd</root>
関連記事:XML (DOM) の基本
コンストラクタ
TransformerFactory ()
protectedです。
独自にサブクラスを作ることは少ないと思いますので、コード例は割愛します。
メソッド
abstract Source getAssociatedStylesheet (Source source, String media, String title, String charset)
final var file = Path.of("R:", "java-work", "sample.xsl");
System.out.println(file); // R:\java-work\sample.xsl
Files.writeString(file, """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="root">
<xxx>
<xsl:value-of select="." />
</xxx>
</xsl:template>
</xsl:stylesheet>
""");
final var xml = """
<?xml-stylesheet type="text/xsl" href="file:///R:/java-work/sample.xsl"?>
<root>abcd</root>
""";
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var transformerFactory = TransformerFactory.newInstance();
final var stylesheet = transformerFactory.getAssociatedStylesheet(
new DOMSource(document), null, null, null);
final var transformer = transformerFactory.newTransformer(stylesheet);
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<xxx>abcd</xxx>
abstract Object getAttribute (String name)
このメソッドの使用例は、setAttribute(String name, Object value) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
abstract ErrorListener getErrorListener ()
このメソッドの使用例は、setErrorListener(ErrorListener listener) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
abstract boolean getFeature (String name)
このメソッドの使用例は、setFeature(String name, boolean value) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
abstract URIResolver getURIResolver ()
このメソッドの使用例は、setURIResolver(URIResolver resolver) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
static TransformerFactory newDefaultInstance ()
newInstance()とほぼ同じです。
API使用例はそちらをご参照ください。
補足:newInstanceとの違い
newInstance は、いろいろと TransformerFactory の実装を探して、なければ最後に組み込みシステムのデフォルト実装を使います。
newDefaultInstance は、組み込みシステムのデフォルト実装をすぐに使います。
よって、メソッドの呼び出し速度は newDefaultInstance のほうが速いです。
自分の環境(openjdk-17.0.1_windows)ではどちらも同じ実装を返しました。
final var defaultFactory = TransformerFactory.newDefaultInstance();
//com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl@6f43c82
System.out.println(defaultFactory);
final var factory = TransformerFactory.newInstance();
//com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl@58e1d9d
System.out.println(factory);
どちらを使うべきか?というのは正直、分かりません…
拡張性が高いのは newInstance のほうなので、個人的には newInstance でよいのではないかなと思います。
static TransformerFactory newInstance ()
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.newDocument();
final var root = document.createElement("root");
document.appendChild(root);
final var text = document.createTextNode("abcd");
root.appendChild(text);
final var transformerFactory = TransformerFactory.newInstance();
final var transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<root>abcd</root>
static TransformerFactory newInstance (String factoryClassName, ClassLoader classLoader)
おそらくサードパーティ製のパーサを使うときのためのAPIです。
本記事ではコード例は割愛します。
abstract Templates newTemplates (Source source)
final var xml = """
<root>abcd</root>
""";
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var xsl = """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="root">
<xxx>
<xsl:value-of select="." />
</xxx>
</xsl:template>
</xsl:stylesheet>
""";
final var transformerFactory = TransformerFactory.newInstance();
final var templates = transformerFactory.newTemplates(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
final var transformer = templates.newTransformer();
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<xxx>abcd</xxx>
abstract Transformer newTransformer ()
このメソッドの使用例は、newInstance() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
abstract Transformer newTransformer (Source source)
このメソッドの使用例は、getAssociatedStylesheet(Source source, String media, String title, String charset) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
abstract void setAttribute (String name, Object value)
final var file = Path.of("R:", "java-work", "sample.xsl");
System.out.println(file); // R:\java-work\sample.xsl
Files.writeString(file, """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="root">
<xxx>
<xsl:value-of select="." />
</xxx>
</xsl:template>
</xsl:stylesheet>
""");
final var xml = """
<root>abcd</root>
""";
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var xsl = """
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="file:///R:/java-work/sample.xsl"/>
</xsl:stylesheet>
""";
final var transformerFactory = TransformerFactory.newInstance();
{
// 標準のデフォルトは "all"
final var ret = transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
System.out.println(ret); // "all"
final var transformer = transformerFactory.newTransformer(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<xxx>abcd</xxx>
}
// すべての外部スタイルシート読み込みを拒否します。
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
{
final var ret = transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
System.out.println(ret); // ""
try {
final var transformer = transformerFactory.newTransformer(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
} catch (TransformerConfigurationException e) {
System.out.println(e);
}
// 結果
// ↓
//javax.xml.transform.TransformerConfigurationException: line 2:
// accessExternalStylesheetプロパティで設定された制限により'file'アクセスが
// 許可されていないため、スタイルシート・ターゲット'sample.xsl'を読み取れま
// せんでした。
}
abstract void setErrorListener (ErrorListener listener)
// 意図的にエラーを起こすために、属性名として許容されていない"xmlns"を追加します。
final var xsl = """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:attribute name="xmlns"/>
</xsl:template>
</xsl:stylesheet>
""";
final var transformerFactory = TransformerFactory.newInstance();
System.out.println(transformerFactory.getErrorListener() != null); // true
final var listener = new ErrorListener() {
@Override
public void warning(TransformerException exception) {
System.out.println("ErrorListener warning : " + exception);
}
@Override
public void error(TransformerException exception) {
System.out.println("ErrorListener error : " + exception);
}
@Override
public void fatalError(TransformerException exception) {
System.out.println("ErrorListener fatalError : " + exception);
}
};
transformerFactory.setErrorListener(listener);
System.out.println(listener == transformerFactory.getErrorListener()); // true
try {
final var transformer = transformerFactory.newTransformer(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
} catch (TransformerConfigurationException e) {
System.out.println("TransformerConfigurationException : " + e);
}
// 結果
// ↓
//ErrorListener error : javax.xml.transform.TransformerException:
// line 4: 属性'xmlns'を呼び出すことはできません
//ErrorListener fatalError : javax.xml.transform.TransformerConfigurationException:
// line 4: 属性'xmlns'を呼び出すことはできません
//TransformerConfigurationException : javax.xml.transform.TransformerConfigurationException:
// line 4: 属性'xmlns'を呼び出すことはできません
abstract void setFeature (String name, boolean value)
関連API : setAttribute(String name, Object value)
final var transformerFactory = TransformerFactory.newInstance();
System.out.println(transformerFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); // false
System.out.println(transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD)); // "all"
System.out.println(transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)); // "all"
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
System.out.println(transformerFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); // true
System.out.println(transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD)); // ""
System.out.println(transformerFactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)); // ""
abstract void setURIResolver (URIResolver resolver)
final var sampleX = Path.of("R:", "java-work", "sample-x.xsl");
System.out.println(sampleX); // R:\java-work\sample-x.xsl
Files.writeString(sampleX, """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="root">
<xxx>
<xsl:value-of select="." />
</xxx>
</xsl:template>
</xsl:stylesheet>
""");
final var sampleY = Path.of("R:", "java-work", "sample-y.xsl");
System.out.println(sampleY); // R:\java-work\sample-y.xsl
Files.writeString(sampleY, """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="root">
<yyy>
<xsl:value-of select="." />
</yyy>
</xsl:template>
</xsl:stylesheet>
""");
final var xml = """
<root>abcd</root>
""";
final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var xsl = """
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="file:///R:/java-work/sample-x.xsl"/>
<xsl:output omit-xml-declaration="yes"/>
</xsl:stylesheet>
""";
final var transformerFactory = TransformerFactory.newInstance();
{
System.out.println(transformerFactory.getURIResolver()); // null
final var transformer = transformerFactory.newTransformer(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<xxx>abcd</xxx>
}
transformerFactory.setURIResolver(new URIResolver() {
@Override
public Source resolve(String href, String base) {
if ("file:///R:/java-work/sample-x.xsl".equals(href)) {
return new StreamSource("file:///R:/java-work/sample-y.xsl");
}
return null;
}
});
{
System.out.println(transformerFactory.getURIResolver() != null); // true
final var transformer = transformerFactory.newTransformer(
new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
final var result = new StreamResult(new StringWriter());
transformer.transform(new DOMSource(document), result);
System.out.println(result.getWriter());
// 結果
// ↓
//<yyy>abcd</yyy>
}