Java : DocumentBuilderFactory (XML) - API使用例
DocumentBuilderFactory (Java SE 22 & JDK 22) の使い方まとめです。
ほとんどのメソッドにサンプルコードがあります。
API仕様書のおともにどうぞ。
概要
DocumentBuilderFactoryは、XMLをDOMで操作する起点となるクラスです。
XML文字列からDOMを構築し、各要素にアクセスする一連の流れは次のようになります。
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) の基本操作
また、XMLの処理には、
- XML外部エンティティ(XXE)インジェクション攻撃
- 指数関数的エンティティ展開攻撃
といった潜在的な攻撃が存在します。
上記の公式ドキュメントでは、XML処理のセキュリティについて詳しく解説されています。
もし信頼していないXMLを読み込む必要がある場合は、上記ドキュメントも合わせてご確認ください。
コンストラクタ
DocumentBuilderFactory ()
protectedです。
独自にサブクラスを作ることは少ないと思いますので、コード例は割愛します。
メソッド
abstract Object getAttribute (String name)
final var dtdFile = Path.of("R:", "java-work", "sample.dtd");
System.out.println(dtdFile); // R:\java-work\sample.dtd
Files.writeString(dtdFile, """
<!ENTITY aaa "bbb">
""");
final var xml = """
<!DOCTYPE root SYSTEM "file:///R:/java-work/sample.dtd">
<root>&aaa;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
// すべての外部DTDの読み込みを許可します。
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all");
final var ret = factory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
System.out.println(ret); // "all"
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
System.out.println(root.getTextContent()); // bbb
}
{
// すべての外部DTDの読み込みを拒否します。
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
final var ret = factory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
System.out.println(ret); // ""
final var builder = factory.newDocumentBuilder();
try {
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
} catch (SAXException e) {
System.out.println(e);
}
// 結果
// ↓
//org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 57;
// 外部DTD: accessExternalDTDプロパティで設定された制限により'file'アクセスが
// 許可されていないため、外部DTD 'sample.dtd'の読取りに失敗しました。
}
abstract boolean getFeature (String name)
// 指数関数的エンティティ展開攻撃の例です。
final var xml = """
<!DOCTYPE root[
<!ENTITY x100 "X">
<!ENTITY x99 "&x100;&x100;">
<!ENTITY x98 "&x99;&x99;">
...
省略
...
<!ENTITY x3 "&x4;&x4;">
<!ENTITY x2 "&x3;&x3;">
<!ENTITY x1 "&x2;&x2;">
]>
<root>&x1;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
// セキュア処理機能(FSP)はデフォルトでtrueです。
final var ret = factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
try {
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
} catch (SAXException e) {
System.out.println(e);
}
// 結果
// ↓
//org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; JAXP00010001:
// パーサーによって、このドキュメント内で"64000"を超えるエンティティ拡張が検出されました。
// これは、JDKによる制限です。
}
// FSPをfalseにします。
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
{
final var ret = factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
// ※注意:エンティティは指数関数的に増えているのでパースに非常に時間がかかります。
//final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
}
Schema getSchema ()
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();
System.out.println(factory.getSchema()); // null
factory.setSchema(schema);
System.out.println(factory.getSchema().equals(schema)); // true
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();
builder.setErrorHandler(errorHandler);
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
System.out.println(root.getTextContent()); // abcd
}
{
// スキーマで指定した文書構造と一致しない例
final var xml = """
<root><child>abcd</child></root>
""";
final var builder = factory.newDocumentBuilder();
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]を含めることはできません。
}
boolean isCoalescing ()
final var xml = """
<root>aaa<![CDATA[<&>]]></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isCoalescing();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
//[#cdata-section: <&>]
}
factory.setCoalescing(true);
{
final var ret = factory.isCoalescing();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa<&>]
}
boolean isExpandEntityReferences ()
final var xml = """
<!DOCTYPE root [
<!ENTITY aaa "bbb">
]>
<root>&aaa;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isExpandEntityReferences();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var child = root.getFirstChild();
System.out.println(child); // [#text: bbb]
}
factory.setExpandEntityReferences(false);
{
final var ret = factory.isExpandEntityReferences();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
if (root.getFirstChild() instanceof EntityReference entityReference) {
System.out.println(entityReference); // [aaa: null]
}
}
boolean isIgnoringComments ()
final var xml = """
<root>aaa<!--bbb--></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isIgnoringComments();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
//[#comment: bbb]
}
factory.setIgnoringComments(true);
{
final var ret = factory.isIgnoringComments();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
}
boolean isIgnoringElementContentWhitespace ()
無視される空白は、テキスト(#PCDATA)を持たないことを宣言した要素が対象となります。
詳細は setIgnoringElementContentWhitespace(boolean whitespace) のAPI仕様もご確認ください。
final var xml = """
<!DOCTYPE root [
<!ELEMENT child-a (dummy?)>
<!ELEMENT child-b (#PCDATA)>
]>
<root>
<child-a> </child-a>
<child-b> </child-b>
</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isIgnoringElementContentWhitespace();
System.out.println(ret); // false
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]
final var childB = document.getElementsByTagName("child-b").item(0);
System.out.println(childB); // [child-b: null]
System.out.println(childA.getFirstChild()); // [#text: ]
System.out.println(childB.getFirstChild()); // [#text: ]
}
factory.setIgnoringElementContentWhitespace(true);
{
final var ret = factory.isIgnoringElementContentWhitespace();
System.out.println(ret); // true
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]
final var childB = document.getElementsByTagName("child-b").item(0);
System.out.println(childB); // [child-b: null]
System.out.println(childA.getFirstChild()); // null
System.out.println(childB.getFirstChild()); // [#text: ]
}
boolean isNamespaceAware ()
final var xml = """
<ns:root xmlns:ns="sample">
<ns:child/>
</ns:root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isNamespaceAware();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var child = document.getElementsByTagNameNS("sample", "child").item(0);
System.out.println(child); // null
}
factory.setNamespaceAware(true);
{
final var ret = factory.isNamespaceAware();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
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]
}
boolean isValidating ()
// 意図的に文書構造(DTD) と一致しないXMLにしています。
final var xml = """
<!DOCTYPE root [
<!ELEMENT root (child-a)>
]>
<root><child-z/></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
final var errorHandler = new DefaultHandler() {
@Override
public void error(SAXParseException e) {
System.out.println("-- ErrorHandler error --");
System.out.println(e);
}
};
{
final var ret = factory.isValidating();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
builder.setErrorHandler(errorHandler);
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var childZ = document.getElementsByTagName("child-z").item(0);
System.out.println(childZ); // [child-z: null]
}
factory.setValidating(true);
{
final var ret = factory.isValidating();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
builder.setErrorHandler(errorHandler);
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 ()
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();
{
final var ret = factory.isXIncludeAware();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var nodes = document.getElementsByTagName("child");
System.out.println(nodes.getLength()); // 0
}
factory.setXIncludeAware(true);
{
final var ret = factory.isXIncludeAware();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
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
}
static DocumentBuilderFactory newDefaultInstance ()
newInstanceとほぼ同じです。
API使用例はそちらをご参照ください。
補足:newInstanceとの違い
newInstance は、いろいろと DocumentBuilderFactory の実装を探して、なければ最後に組み込みシステムのデフォルト実装を使います。 newDefaultInstance は、組み込みシステムのデフォルト実装をすぐに使います。
よって、メソッドの呼び出し速度は newDefaultInstance のほうが速いです。
自分の環境(openjdk-22.0.2_windows)ではどちらも同じ実装を返しました。
final var defaultFactory = DocumentBuilderFactory.newDefaultInstance();
// com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl@7857fe2
System.out.println(defaultFactory);
final var factory = DocumentBuilderFactory.newInstance();
// com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl@5340477f
System.out.println(factory);
どちらを使うべきか?というのは正直、分かりません…
拡張性が高いのは newInstance のほうなので、個人的には newInstance でよいのではないかなと思います。
static DocumentBuilderFactory newDefaultNSInstance ()
final var nsFactory = DocumentBuilderFactory.newDefaultNSInstance();
System.out.println(nsFactory.isNamespaceAware()); // true
final var factory = DocumentBuilderFactory.newDefaultInstance();
System.out.println(factory.isNamespaceAware()); // false
abstract DocumentBuilder newDocumentBuilder ()
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
static DocumentBuilderFactory newInstance ()
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
static DocumentBuilderFactory newInstance (String factoryClassName, ClassLoader classLoader)
おそらくサードパーティ製のパーサを使うときのためのAPIです。
本記事ではコード例は割愛します。
static DocumentBuilderFactory newNSInstance ()
final var nsFactory = DocumentBuilderFactory.newNSInstance();
System.out.println(nsFactory.isNamespaceAware()); // true
final var factory = DocumentBuilderFactory.newInstance();
System.out.println(factory.isNamespaceAware()); // false
static DocumentBuilderFactory newNSInstance (String factoryClassName, ClassLoader classLoader)
おそらくサードパーティ製のパーサを使うときのためのAPIです。
本記事ではコード例は割愛します。
abstract void setAttribute (String name, Object value)
final var dtdFile = Path.of("R:", "java-work", "sample.dtd");
System.out.println(dtdFile); // R:\java-work\sample.dtd
Files.writeString(dtdFile, """
<!ENTITY aaa "bbb">
""");
final var xml = """
<!DOCTYPE root SYSTEM "file:///R:/java-work/sample.dtd">
<root>&aaa;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
// すべての外部DTDの読み込みを許可します。
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all");
final var ret = factory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
System.out.println(ret); // "all"
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
System.out.println(root.getTextContent()); // bbb
}
{
// すべての外部DTDの読み込みを拒否します。
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
final var ret = factory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
System.out.println(ret); // ""
final var builder = factory.newDocumentBuilder();
try {
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
} catch (SAXException e) {
System.out.println(e);
}
// 結果
// ↓
//org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 57;
// 外部DTD: accessExternalDTDプロパティで設定された制限により'file'アクセスが
// 許可されていないため、外部DTD 'sample.dtd'の読取りに失敗しました。
}
void setCoalescing (boolean coalescing)
final var xml = """
<root>aaa<![CDATA[<&>]]></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isCoalescing();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
//[#cdata-section: <&>]
}
factory.setCoalescing(true);
{
final var ret = factory.isCoalescing();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa<&>]
}
void setExpandEntityReferences (boolean expandEntityRef)
final var xml = """
<!DOCTYPE root [
<!ENTITY aaa "bbb">
]>
<root>&aaa;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isExpandEntityReferences();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var child = root.getFirstChild();
System.out.println(child); // [#text: bbb]
}
factory.setExpandEntityReferences(false);
{
final var ret = factory.isExpandEntityReferences();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
if (root.getFirstChild() instanceof EntityReference entityReference) {
System.out.println(entityReference); // [aaa: null]
}
}
abstract void setFeature (String name, boolean value)
// 指数関数的エンティティ展開攻撃の例です。
final var xml = """
<!DOCTYPE root[
<!ENTITY x100 "X">
<!ENTITY x99 "&x100;&x100;">
<!ENTITY x98 "&x99;&x99;">
...
省略
...
<!ENTITY x3 "&x4;&x4;">
<!ENTITY x2 "&x3;&x3;">
<!ENTITY x1 "&x2;&x2;">
]>
<root>&x1;</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
// セキュア処理機能(FSP)はデフォルトでtrueです。
final var ret = factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
try {
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
} catch (SAXException e) {
System.out.println(e);
}
// 結果
// ↓
//org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; JAXP00010001:
// パーサーによって、このドキュメント内で"64000"を超えるエンティティ拡張が検出されました。
// これは、JDKによる制限です。
}
// FSPをfalseにします。
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
{
final var ret = factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
// ※注意:エンティティは指数関数的に増えているのでパースに非常に時間がかかります。
//final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
}
void setIgnoringComments (boolean ignoreComments)
final var xml = """
<root>aaa<!--bbb--></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isIgnoringComments();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
//[#comment: bbb]
}
factory.setIgnoringComments(true);
{
final var ret = factory.isIgnoringComments();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
final var nodes = root.getChildNodes();
System.out.println("-- nodes --");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
// 結果
// ↓
//-- nodes --
//[#text: aaa]
}
void setIgnoringElementContentWhitespace (boolean whitespace)
無視される空白は、テキスト(#PCDATA)を持たないことを宣言した要素が対象となります。
詳細は setIgnoringElementContentWhitespace(boolean whitespace) のAPI仕様もご確認ください。
final var xml = """
<!DOCTYPE root [
<!ELEMENT child-a (dummy?)>
<!ELEMENT child-b (#PCDATA)>
]>
<root>
<child-a> </child-a>
<child-b> </child-b>
</root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isIgnoringElementContentWhitespace();
System.out.println(ret); // false
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]
final var childB = document.getElementsByTagName("child-b").item(0);
System.out.println(childB); // [child-b: null]
System.out.println(childA.getFirstChild()); // [#text: ]
System.out.println(childB.getFirstChild()); // [#text: ]
}
factory.setIgnoringElementContentWhitespace(true);
{
final var ret = factory.isIgnoringElementContentWhitespace();
System.out.println(ret); // true
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]
final var childB = document.getElementsByTagName("child-b").item(0);
System.out.println(childB); // [child-b: null]
System.out.println(childA.getFirstChild()); // null
System.out.println(childB.getFirstChild()); // [#text: ]
}
void setNamespaceAware (boolean awareness)
final var xml = """
<ns:root xmlns:ns="sample">
<ns:child/>
</ns:root>
""";
final var factory = DocumentBuilderFactory.newInstance();
{
final var ret = factory.isNamespaceAware();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var child = document.getElementsByTagNameNS("sample", "child").item(0);
System.out.println(child); // null
}
factory.setNamespaceAware(true);
{
final var ret = factory.isNamespaceAware();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
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]
}
void setSchema (Schema schema)
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();
System.out.println(factory.getSchema()); // null
factory.setSchema(schema);
System.out.println(factory.getSchema().equals(schema)); // true
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();
builder.setErrorHandler(errorHandler);
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var root = document.getDocumentElement();
System.out.println(root); // [root: null]
System.out.println(root.getTextContent()); // abcd
}
{
// スキーマで指定した文書構造と一致しない例
final var xml = """
<root><child>abcd</child></root>
""";
final var builder = factory.newDocumentBuilder();
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]を含めることはできません。
}
void setValidating (boolean validating)
// 意図的に文書構造(DTD) と一致しないXMLにしています。
final var xml = """
<!DOCTYPE root [
<!ELEMENT root (child-a)>
]>
<root><child-z/></root>
""";
final var factory = DocumentBuilderFactory.newInstance();
final var errorHandler = new DefaultHandler() {
@Override
public void error(SAXParseException e) {
System.out.println("-- ErrorHandler error --");
System.out.println(e);
}
};
{
final var ret = factory.isValidating();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
builder.setErrorHandler(errorHandler);
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var childZ = document.getElementsByTagName("child-z").item(0);
System.out.println(childZ); // [child-z: null]
}
factory.setValidating(true);
{
final var ret = factory.isValidating();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
builder.setErrorHandler(errorHandler);
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)"と一致する必要があります。
}
void setXIncludeAware (boolean state)
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();
{
final var ret = factory.isXIncludeAware();
System.out.println(ret); // false
final var builder = factory.newDocumentBuilder();
final var document = builder.parse(new ByteArrayInputStream(xml.getBytes()));
final var nodes = document.getElementsByTagName("child");
System.out.println(nodes.getLength()); // 0
}
factory.setXIncludeAware(true);
{
final var ret = factory.isXIncludeAware();
System.out.println(ret); // true
final var builder = factory.newDocumentBuilder();
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
}