広告

Java : Transformer (XML) - API使用例

Transformer (Java SE 22 & JDK 22) の使い方まとめです。
ほとんどのメソッドにサンプルコードがあります。
API仕様書のおともにどうぞ。


概要

このabstractクラスのインスタンスは、ソース・ツリーを結果ツリーに変換することができます。

クラス構成

Transformerクラスは以下の変換を行います。

  • XMLオブジェクト(DOMやSAX、StAX) → XML形式の文字列やファイル
  • DOM → SAX などのXMLオブジェクト間の変換
  • XSLT

関連記事 : XML (DOM) の基本操作

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 factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer();

final var source = new DOMSource(document);
final var result = new StreamResult(new StringWriter());
transformer.transform(source, result);

//<?xml version="1.0" encoding="UTF-8" standalone="no"?><root>abcd</root>
System.out.println(result.getWriter());

コンストラクタ

Transformer ()

デフォルトのコンストラクタが意図的に保護されます。

protectedです。
独自にサブクラスを作ることは少ないと思いますので、コード例は割愛します。

メソッド

abstract void clearParameters ()

setParameterを使用して設定されたすべてのパラメータをクリアします。

final var xml = """
        <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:param name="param">aaaa</xsl:param>

          <xsl:template match="root">
            <xsl:copy-of select="$param" />
          </xsl:template>

        </xsl:stylesheet>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

System.out.println(transformer.getParameter("param")); // null
transformer.setParameter("param", "bbbb");

{
    System.out.println(transformer.getParameter("param")); // bbbb

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //bbbb
    System.out.println(result.getWriter());
}

transformer.clearParameters();

{
    System.out.println(transformer.getParameter("param")); // null

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //aaaa
    System.out.println(result.getWriter());
}

abstract ErrorListener getErrorListener ()

変換に有効なエラー・イベント・ハンドラを取得します。

// 意図的にエラーを起こすために、間違った構文のXMLを使います。
final var xml = """
        <root>
            <<<child>aaa</child>
        </root>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer();

final var listener = new ErrorListener() {
    @Override
    public void warning(TransformerException exception) {
        System.out.println("-- ErrorListener warning --");
        System.out.println(exception);
    }

    @Override
    public void error(TransformerException exception) {
        System.out.println("-- ErrorListener error --");
        System.out.println(exception);
    }

    @Override
    public void fatalError(TransformerException exception) {
        System.out.println("-- ErrorListener fatalError --");
        System.out.println(exception);
    }
};

transformer.setErrorListener(listener);
System.out.println(listener == transformer.getErrorListener()); // true

final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
final var result = new StreamResult(new StringWriter());

try {
    transformer.transform(source, result);
} catch (TransformerException e) {
    System.out.println("-- TransformerException --");
    System.out.println(e);
}

// 結果
// ↓
//-- ErrorListener error --
//javax.xml.transform.TransformerException:
// 要素のコンテンツは、整形式の文字データまたはマークアップで構成されている必要があります。
//-- TransformerException --
//javax.xml.transform.TransformerException:
// org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 6;
// 要素のコンテンツは、整形式の文字データまたはマークアップで構成されている必要があります。

abstract Properties getOutputProperties ()

変換のための出力プロパティのコピーを取得します。

final var xml = """
        <root><child>aaa</child></root>
        """;

final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));

final var transformer = TransformerFactory.newInstance().newTransformer();

{
    final var ret = transformer.getOutputProperties();
    System.out.println(ret.size()); // 0

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<?xml version="1.0" encoding="UTF-8" standalone="no"?><root><child>aaa</child></root>
    System.out.println(result.getWriter());
}

final var properties = new Properties();
properties.setProperty(OutputKeys.INDENT, "yes");
properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

transformer.setOutputProperties(properties);

{
    final var ret = transformer.getOutputProperties();
    System.out.println(ret); // {indent=yes, omit-xml-declaration=yes}

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>
    //    <child>aaa</child>
    //</root>
    System.out.println(result.getWriter());
}

abstract String getOutputProperty (String name)

transformerに有効な出力プロパティを取得します。

final var xml = """
        <root><child>aaa</child></root>
        """;

final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));

final var transformer = TransformerFactory.newInstance().newTransformer();

{
    final var ret1 = transformer.getOutputProperty(OutputKeys.INDENT);
    System.out.println(ret1); // "no"

    final var ret2 = transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION);
    System.out.println(ret2); // "no"

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<?xml version="1.0" encoding="UTF-8" standalone="no"?><root><child>aaa</child></root>
    System.out.println(result.getWriter());
}

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

{
    final var ret1 = transformer.getOutputProperty(OutputKeys.INDENT);
    System.out.println(ret1); // "yes"

    final var ret2 = transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION);
    System.out.println(ret2); // "yes"

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>
    //    <child>aaa</child>
    //</root>
    System.out.println(result.getWriter());
}

abstract Object getParameter (String name)

setParameterを使用して明示的に設定されたパラメータを取得します。

final var xml = """
        <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:param name="param">aaaa</xsl:param>

          <xsl:template match="root">
            <xsl:copy-of select="$param" />
          </xsl:template>

        </xsl:stylesheet>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

System.out.println(transformer.getParameter("param")); // null
transformer.setParameter("param", "bbbb");

{
    System.out.println(transformer.getParameter("param")); // bbbb

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //bbbb
    System.out.println(result.getWriter());
}

transformer.clearParameters();

{
    System.out.println(transformer.getParameter("param")); // null

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //aaaa
    System.out.println(result.getWriter());
}

abstract URIResolver getURIResolver ()

document()で使用されるURIを解決するのに使用されるオブジェクトを取得します。

final var sampleA = Path.of("R:", "java-work", "sample-a.xml");
System.out.println(sampleA); // R:\java-work\sample-a.xml

Files.writeString(sampleA, """
        <root>aaa</root>
        """);

final var sampleB = Path.of("R:", "java-work", "sample-b.xml");
System.out.println(sampleB); // R:\java-work\sample-b.xml

Files.writeString(sampleB, """
        <root>bbb</root>
        """);

final var xml = """
        <root/>
        """;

final var xsl = """
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
          <xsl:output omit-xml-declaration="yes" />
          <xsl:variable name="doc" select="document('file:///R:/java-work/sample-a.xml')" />

          <xsl:template match="/">
            <xsl:copy-of select="$doc" />
          </xsl:template>

        </xsl:stylesheet>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

{
    System.out.println(transformer.getURIResolver()); // null

    final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>aaa</root>
    System.out.println(result.getWriter());
}

final var urlResolver = new URIResolver() {
    @Override
    public Source resolve(String href, String base) {
        if ("file:///R:/java-work/sample-a.xml".equals(href)) {
            return new StreamSource("file:///R:/java-work/sample-b.xml");
        }

        return null;
    }
};

transformer.setURIResolver(urlResolver);

{
    System.out.println(transformer.getURIResolver() == urlResolver); // true

    final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>bbb</root>
    System.out.println(result.getWriter());
}

void reset ()

このTransformerを元の構成にリセットします。

final var transformer = TransformerFactory.newInstance().newTransformer();

transformer.setParameter("param", "bbbb");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

System.out.println(transformer.getParameter("param")); // "bbbb"
System.out.println(transformer.getOutputProperty(OutputKeys.INDENT)); // "yes"
System.out.println(transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION)); // "yes"

transformer.reset();

System.out.println(transformer.getParameter("param")); // null
System.out.println(transformer.getOutputProperty(OutputKeys.INDENT)); // "no"
System.out.println(transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION)); // "no"

abstract void setErrorListener (ErrorListener listener)

変換に有効なエラー・イベント・リスナーを設定します。

// 意図的にエラーを起こすために、間違った構文のXMLを使います。
final var xml = """
        <root>
            <<<child>aaa</child>
        </root>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer();

final var listener = new ErrorListener() {
    @Override
    public void warning(TransformerException exception) {
        System.out.println("-- ErrorListener warning --");
        System.out.println(exception);
    }

    @Override
    public void error(TransformerException exception) {
        System.out.println("-- ErrorListener error --");
        System.out.println(exception);
    }

    @Override
    public void fatalError(TransformerException exception) {
        System.out.println("-- ErrorListener fatalError --");
        System.out.println(exception);
    }
};

transformer.setErrorListener(listener);
System.out.println(listener == transformer.getErrorListener()); // true

final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
final var result = new StreamResult(new StringWriter());

try {
    transformer.transform(source, result);
} catch (TransformerException e) {
    System.out.println("-- TransformerException --");
    System.out.println(e);
}

// 結果
// ↓
//-- ErrorListener error --
//javax.xml.transform.TransformerException:
// 要素のコンテンツは、整形式の文字データまたはマークアップで構成されている必要があります。
//-- TransformerException --
//javax.xml.transform.TransformerException:
// org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 6;
// 要素のコンテンツは、整形式の文字データまたはマークアップで構成されている必要があります。

abstract void setOutputProperties (Properties oformat)

変換の出力プロパティを設定します。

final var xml = """
        <root><child>aaa</child></root>
        """;

final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));

final var transformer = TransformerFactory.newInstance().newTransformer();

{
    final var ret = transformer.getOutputProperties();
    System.out.println(ret.size()); // 0

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<?xml version="1.0" encoding="UTF-8" standalone="no"?><root><child>aaa</child></root>
    System.out.println(result.getWriter());
}

final var properties = new Properties();
properties.setProperty(OutputKeys.INDENT, "yes");
properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

transformer.setOutputProperties(properties);

{
    final var ret = transformer.getOutputProperties();
    System.out.println(ret); // {indent=yes, omit-xml-declaration=yes}

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>
    //    <child>aaa</child>
    //</root>
    System.out.println(result.getWriter());
}

abstract void setOutputProperty (String name, String value)

変換に有効な出力プロパティを設定します。

final var xml = """
        <root><child>aaa</child></root>
        """;

final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));

final var transformer = TransformerFactory.newInstance().newTransformer();

{
    final var ret1 = transformer.getOutputProperty(OutputKeys.INDENT);
    System.out.println(ret1); // "no"

    final var ret2 = transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION);
    System.out.println(ret2); // "no"

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<?xml version="1.0" encoding="UTF-8" standalone="no"?><root><child>aaa</child></root>
    System.out.println(result.getWriter());
}

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

{
    final var ret1 = transformer.getOutputProperty(OutputKeys.INDENT);
    System.out.println(ret1); // "yes"

    final var ret2 = transformer.getOutputProperty(OutputKeys.OMIT_XML_DECLARATION);
    System.out.println(ret2); // "yes"

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>
    //    <child>aaa</child>
    //</root>
    System.out.println(result.getWriter());
}

abstract void setParameter (String name, Object value)

変換のパラメータを追加します。

final var xml = """
        <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:param name="param">aaaa</xsl:param>

          <xsl:template match="root">
            <xsl:copy-of select="$param" />
          </xsl:template>

        </xsl:stylesheet>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

System.out.println(transformer.getParameter("param")); // null
transformer.setParameter("param", "bbbb");

{
    System.out.println(transformer.getParameter("param")); // bbbb

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //bbbb
    System.out.println(result.getWriter());
}

transformer.clearParameters();

{
    System.out.println(transformer.getParameter("param")); // null

    final var source = new DOMSource(document);
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //aaaa
    System.out.println(result.getWriter());
}

abstract void setURIResolver (URIResolver resolver)

document()で使用されるURIを解決するのに使用されるオブジェクトを設定します。

final var sampleA = Path.of("R:", "java-work", "sample-a.xml");
System.out.println(sampleA); // R:\java-work\sample-a.xml

Files.writeString(sampleA, """
        <root>aaa</root>
        """);

final var sampleB = Path.of("R:", "java-work", "sample-b.xml");
System.out.println(sampleB); // R:\java-work\sample-b.xml

Files.writeString(sampleB, """
        <root>bbb</root>
        """);

final var xml = """
        <root/>
        """;

final var xsl = """
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
          <xsl:output omit-xml-declaration="yes" />
          <xsl:variable name="doc" select="document('file:///R:/java-work/sample-a.xml')" />

          <xsl:template match="/">
            <xsl:copy-of select="$doc" />
          </xsl:template>

        </xsl:stylesheet>
        """;

final var factory = TransformerFactory.newInstance();
final var transformer = factory.newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

{
    System.out.println(transformer.getURIResolver()); // null

    final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>aaa</root>
    System.out.println(result.getWriter());
}

final var urlResolver = new URIResolver() {
    @Override
    public Source resolve(String href, String base) {
        if ("file:///R:/java-work/sample-a.xml".equals(href)) {
            return new StreamSource("file:///R:/java-work/sample-b.xml");
        }

        return null;
    }
};

transformer.setURIResolver(urlResolver);

{
    System.out.println(transformer.getURIResolver() == urlResolver); // true

    final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
    final var result = new StreamResult(new StringWriter());
    transformer.transform(source, result);

    //<root>bbb</root>
    System.out.println(result.getWriter());
}

abstract void transform (Source xmlSource, Result outputTarget)

XML SourceをResultに変換します。

// 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 transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

final var source = new DOMSource(document);
final var result = new StreamResult(new StringWriter());
transformer.transform(source, result);

//<root>abcd</root>
System.out.println(result.getWriter());
// XML文字列 → XSLによる変換

final var xml = """
        <root>abcd</root>
        """;

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="/">012<xsl:value-of select="." />XYZ</xsl:template>

        </xsl:stylesheet>
        """;

final var transformer = TransformerFactory.newInstance().newTransformer(
        new StreamSource(new ByteArrayInputStream(xsl.getBytes())));

final var source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
final var result = new StreamResult(new StringWriter());
transformer.transform(source, result);

//012abcdXYZ
System.out.println(result.getWriter());
// DOM → SAX

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 transformer = TransformerFactory.newInstance().newTransformer();

final var handler = new DefaultHandler() {

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        System.out.println("startElement : " + qName);
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        System.out.println("endElement : " + qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        System.out.println("text : " + new String(ch, start, length));
    }
};

final var source = new DOMSource(document);
final var result = new SAXResult(handler);

//startElement : root
//text : abcd
//endElement : root
transformer.transform(source, result);

関連記事

ページの先頭へ