広告

Java : DocumentBuilder (XML) - API使用例

DocumentBuilder (Java SE 17 & JDK 17) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

XMLドキュメントからDOM Documentインスタンスを取得するAPIを定義します。 このクラスを使用すると、アプリケーション・プログラマはXMLからDocumentを取得できます。

クラス構成

DocumentBuilderクラスは、XML形式の文字列やファイルから Documentクラスを生成します。
DocumentBuilderそのものを生成するには DocumentBuilderFactory を使います。

final var xml = """
        <root>
            <child-a>AAA</child-a>
            <child-b>BBB</child-b>
        </root>
        """;

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

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

final var childA = document.getElementsByTagName("child-a").item(0);
System.out.println(childA); // [child-a: null]
System.out.println(childA.getTextContent()); // AAA

final var childB = document.getElementsByTagName("child-b").item(0);
System.out.println(childB); // [child-b: null]
System.out.println(childB.getTextContent()); // BBB

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


共通で使うコード

本記事のAPI使用例では、利便性のために以下の printDocument メソッドを共通処理として使います。

// DocumentをXMLでコンソールに出力します。
// 見やすくするためにインデントを付け、<?xml ~ ?>は非表示にしています。
// DocumentTypeがある場合は出力します。
public void printDocument(Document document) throws TransformerException {
    final var transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

    final var docType = document.getDoctype();
    if (docType != null) {
        final var publicId = docType.getPublicId();
        if (publicId != null) {
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, publicId);
        }
        final var systemId = docType.getSystemId();
        if (systemId != null) {
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemId);
        }
    }

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

    System.out.print(result.getWriter());
}

使用例です。

final var builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final var document = builder.newDocument();

final var root = document.createElement("root");
System.out.println(root); // [root: null]

document.appendChild(root);

final var child = document.createElement("child");
System.out.println(child); // [child: null]

root.appendChild(child);

final var text = document.createTextNode("abcd");
System.out.println(text); // [#text: abcd]

child.appendChild(text);

//<root>
//    <child>abcd</child>
//</root>
printDocument(document);

コンストラクタ

DocumentBuilder ()

protectedコンストラクタです。

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

メソッド

abstract DOMImplementation getDOMImplementation ()

DOMImplementationオブジェクトのインスタンスを取得します。

printDocumentメソッドについてはこちらをご参照ください。

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

final var domImpl = builder.getDOMImplementation();
final var docType = domImpl.createDocumentType(
        "root", null, "file:///R:/java-work/sample.dtd");
System.out.println(docType); // [root: null]

final var document = domImpl.createDocument(null, "root", docType);

//<!DOCTYPE root SYSTEM "file:///R:/java-work/sample.dtd">
//<root/>
printDocument(document);

Schema getSchema ()

XMLプロセッサによって使用されるSchemaへの参照を取得します。

printDocumentメソッドについてはこちらをご参照ください。

final var xsd = """
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <xsd:element name="root" type="xsd:string"/>
        </xsd:schema>
        """;

final var schemaFactory = SchemaFactory.newDefaultInstance();
final var schema = schemaFactory.newSchema(
        new StreamSource(new ByteArrayInputStream(xsd.getBytes())));

final var factory = DocumentBuilderFactory.newInstance();
factory.setSchema(schema);

final var errorHandler = new DefaultHandler() {
    @Override
    public void error(SAXParseException e) {
        System.out.println("-- ErrorHandler error --");
        System.out.println(e);
    }
};

{
    // スキーマで指定した文書構造と一致する例
    final var xml = """
            <root>abcd</root>
            """;

    final var builder = factory.newDocumentBuilder();
    System.out.println(builder.getSchema().equals(schema)); // true

    builder.setErrorHandler(errorHandler);

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

    //<root>abcd</root>
    printDocument(document);
}

{
    // スキーマで指定した文書構造と一致しない例
    final var xml = """
            <root><child>abcd</child></root>
            """;

    final var builder = factory.newDocumentBuilder();
    System.out.println(builder.getSchema().equals(schema)); // true

    builder.setErrorHandler(errorHandler);

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

    // 結果
    // ↓
    //-- ErrorHandler error --
    //org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 33; cvc-type.3.1.2:
    // 要素'root'は単純型であるため、要素情報アイテム[children]を含めることはできません。
}

abstract boolean isNamespaceAware ()

このパーサーが名前空間を認識するように構成されているかどうかを示します。

final var xml = """
        <ns:root xmlns:ns="sample">
            <ns:child/>
        </ns:root>
        """;

final var factory = DocumentBuilderFactory.newNSInstance();

final var builder = factory.newDocumentBuilder();
System.out.println(builder.isNamespaceAware()); // true

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

final var child = document.getElementsByTagNameNS("sample", "child").item(0);
System.out.println(child); // [ns:child: null]

abstract boolean isValidating ()

このパーサーがXMLドキュメントを検証するように構成されているかどうかを示します。

// 意図的に文書構造と一致しないXMLにしています。
final var xml = """
        <!DOCTYPE root [
            <!ELEMENT root (child-a)>
        ]>
        <root><child-z/></root>
        """;

final var factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);

final var builder = factory.newDocumentBuilder();
System.out.println(builder.isValidating()); // true

builder.setErrorHandler(new DefaultHandler() {
    @Override
    public void error(SAXParseException e) throws SAXException {
        System.out.println("-- ErrorHandler error --");
        System.out.println(e);
    }
});

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

// 結果
// ↓
//-- ErrorHandler error --
//org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 17;
// 要素タイプ"child-z"を宣言する必要があります。
//-- ErrorHandler error --
//org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 24;
// 要素タイプ"root"のコンテンツは"(child-a)"と一致する必要があります。

boolean isXIncludeAware ()

このパーサーのXInclude処理モードを取得します。

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

Files.writeString(sampleFile, """
        <child>abcd</child>
        """);

final var xml = """
        <root xmlns:xi="http://www.w3.org/2001/XInclude">
            <xi:include href="file:///R:/java-work/sample.xml" parse="xml" />
        </root>
        """;

final var factory = DocumentBuilderFactory.newNSInstance();
factory.setXIncludeAware(true);

final var builder = factory.newDocumentBuilder();
System.out.println(builder.isXIncludeAware()); // true

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

final var child = document.getElementsByTagName("child").item(0);
System.out.println(child); // [child: null]
System.out.println(child.getTextContent()); // abcd

abstract Document newDocument ()

DOMツリーの構築に使用するDOM Documentオブジェクトの新しいインスタンスを取得します。

printDocumentメソッドについてはこちらをご参照ください。

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

final var document = builder.newDocument();

final var root = document.createElement("root");
document.appendChild(root);

final var child = document.createElement("child");
root.appendChild(child);

child.setAttribute("aa", "AA");

final var text = document.createTextNode("abcd");
child.appendChild(text);

//<root>
//    <child aa="AA">abcd</child>
//</root>
printDocument(document);

Document parse (File f)

指定されたファイルの内容をXMLドキュメントとして構文解析し、新しいDOM Documentオブジェクトを返します。

printDocumentメソッドについてはこちらをご参照ください。

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

Files.writeString(path, """
        <root><child>abcd</child></root>
        """);

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

final var document = builder.parse(path.toFile());

//<root>
//    <child>abcd</child>
//</root>
printDocument(document);

Document parse (InputStream is)

指定されたInputStreamの内容をXMLドキュメントとして構文解析し、新しいDOM Documentオブジェクトを返します。

printDocumentメソッドについてはこちらをご参照ください。

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

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

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

//<root>
//    <child>abcd</child>
//</root>
printDocument(document);

Document parse (InputStream is, String systemId)

指定されたInputStreamの内容をXMLドキュメントとして構文解析し、新しいDOM Documentオブジェクトを返します。

printDocumentメソッドについてはこちらをご参照ください。

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

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

final var baseUri = Path.of("R:", "java-work").toUri();
System.out.println(baseUri); // file:///R:/java-work/

final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()),
        baseUri.toString());
System.out.println(document.getBaseURI()); // file:///R:/java-work/

//<root>
//    <child>abcd</child>
//</root>
printDocument(document);

Document parse (String uri)

指定されたURIの内容をXMLドキュメントとして構文解析し、新しいDOM Documentオブジェクトを返します。

printDocumentメソッドについてはこちらをご参照ください。

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

Files.writeString(path, """
        <root><child>abcd</child></root>
        """);

final var uri = path.toUri();
System.out.println(uri); // file:///R:/java-work/sample.xml

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

final var document = builder.parse(uri.toString());

//<root>
//    <child>abcd</child>
//</root>
printDocument(document);

abstract Document parse (InputSource is)

指定された入力ソースの内容をXMLドキュメントとして構文解析し、新しいDOM Documentオブジェクトを返します。

printDocumentメソッドについてはこちらをご参照ください。

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

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

try (final var reader = new StringReader(xml)) {
    final var is = new InputSource(reader);
    final var document = builder.parse(is);

    //<root>
    //    <child>abcd</child>
    //</root>
    printDocument(document);
}

void reset ()

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

final var dtdB = Path.of("R:", "java-work", "bbb.dtd");
System.out.println(dtdB); // R:\java-work\bbb.dtd

Files.writeString(dtdB, """
        <!ENTITY aaa "bbb">
        """);

final var dtdC = Path.of("R:", "java-work", "ccc.dtd");
System.out.println(dtdC); // R:\java-work\ccc.dtd

Files.writeString(dtdC, """
        <!ENTITY aaa "ccc">
        """);

final var xml = """
        <!DOCTYPE root SYSTEM "file:///R:/java-work/bbb.dtd">
        <root>&aaa;</root>
        """;

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

builder.setEntityResolver((publicId, systemId) -> {
    if ("file:///R:/java-work/bbb.dtd".equals(systemId)) {
        return new InputSource(dtdC.toUri().toString());
    } else {
        return null;
    }
});

final var document1 = builder.parse(new ByteArrayInputStream(xml.getBytes()));

//<!DOCTYPE root SYSTEM "file:///R:/java-work/bbb.dtd">
//<root>ccc</root>
printDocument(document1);

builder.reset();

final var document2 = builder.parse(new ByteArrayInputStream(xml.getBytes()));

//<!DOCTYPE root SYSTEM "file:///R:/java-work/bbb.dtd">
//<root>bbb</root>
printDocument(document2);

abstract void setEntityResolver (EntityResolver er)

構文解析するXMLドキュメントに存在するエンティティを解決するのに使用されるEntityResolverを指定します。

printDocumentメソッドについてはこちらをご参照ください。

final var xml = """
        <!DOCTYPE root SYSTEM "file:///R:/java-work/xxx.dtd">
        <root>&aaa;</root>
        """;

final var factory = DocumentBuilderFactory.newInstance();
final var builder = factory.newDocumentBuilder();

builder.setEntityResolver((publicId, systemId) -> {
    if ("file:///R:/java-work/xxx.dtd".equals(systemId)) {
        final var dtd = """
                <!ENTITY aaa "bbb">
                """;
        return new InputSource(new ByteArrayInputStream(dtd.getBytes()));
    } else {
        return null;
    }
});

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

//<!DOCTYPE root SYSTEM "file:///R:/java-work/xxx.dtd">
//<root>bbb</root>
printDocument(document);

abstract void setErrorHandler (ErrorHandler eh)

パーサーによって使用されるErrorHandlerを指定します。

このメソッドの使用例は、isValidating() にまとめて記載しました。
そちらのAPI使用例をご参照ください。


関連記事

ページの先頭へ