解答例 - 実習課題1 - 6.DTD(DocumentType)
(実習課題1)
XMLパーサには、DTDを解読した上でXML文書がDTDに沿った構造になっているか解析するvalidate機能が提供されています。ただし、アプリケーションで使用するXMLの構造があらかじめ決まっている場合、パーサがDTDを読み取る処理がオーバーヘッドになります。そこで、以下のコンソールプログラムを作成しなさい。
- 引数に与えられたXML文書が、以下のDTDで表される構造になっているか、判定するプログラム
- 与えられたXMLが以下の条件を満たすときのみ、DTDに沿ったXMLファイルかどうか、解析する。解析結果は標準出力に表示する。
- ルート要素 :person
- 公開識別子: -//Four Dimensional Data, Inc.//DTD DOM Example 1.0//EN
- システム識別子: http://www.techscore.com/tech/Java/DOM/DOMExample.dtd
- 上記以外のDTDが指定されている場合、エラーメッセージを標準エラーに出力し、プログラムを終了する。
- XMLパーサのvalidate機能を使用しない。
Java 1.4付属のパーサを使用する場合、デフォルトでXMLパーサのvalidate機能は使用できないようになっています。また、以下のようにして、validate機能を使用しないように設定することが可能です。DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false);
- 解析するXML文書にコメントやエンティティは含まれないものとしてよい。
- DTDは以下の通り。
<!-- person要素がルート要素となる --> <!ELEMENT person (name,age,license*)>
※"http://www.techscore.com/tech/Java/DOM/DOMExample.dtd"が参照できる環境でプログラムを実行する必要があります。
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT license (#PCDATA)>
解答例
package com.techscore.dom.chapter6.exercise1;
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* DtdValidator.java
*
* TECHSCORE Java XML DOM XSLT 6章 実習課題1
*
* Copyright (c) 2004 Four-Dimensional Data, Inc.
*/
public class DtdValidator {
private static final String[] ELEMENT_NAMES = {"name", "age", "license"};
public static void main(String[] args) throws Exception {
if (args.length < 1) {
System.out.println("引数にXML文書ファイルを指定してください");
return;
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
Document document = factory.newDocumentBuilder()
.parse(new File(args[0]));
DocumentType dtd = document.getDoctype();
if(dtd == null){
System.err.println("DOCTYPE宣言がありません");
return;
}
// XMLファイルを解析するかどうか判定する
Element person = document.getDocumentElement();
if ((!"person".equals(dtd.getName()))
|| (!"-//Four Dimensional Data, Inc.//DTD DOM Example 1.0//EN".equals(dtd.getPublicId()))
|| (!"http://www.techscore.com/tech/Java/DOM/DOMExample.dtd".equals(dtd.getSystemId()))) {
System.err.println("DTDが規定されたものではありません");
return;
}
int idx = 0;
NodeList nodeList = person.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) {
if (!ELEMENT_NAMES[Math.min(idx++, 2)].equals(nodeList.item(i)
.getNodeName())) {
System.err.println("このXML文書は"
+ "『<!ELEMENT person (name,age,license*)>』"
+ "という指定に従っていません");
return;
} else if (nodeList.item(i).hasChildNodes()) {
NodeList childList = nodeList.item(i).getChildNodes();
for (int j = 0; j < childList.getLength(); j++) {
if (childList.item(j).getNodeType() != Node.TEXT_NODE) {
System.err.println("このXML文書は" + "『<!ELEMENT "
+ nodeList.item(i).getNodeName()
+ " #PCDATA』" + "という指定に従っていません");
return;
}
}
}
} else if (nodeList.item(i).getNodeType() == Node.TEXT_NODE) {
if (!nodeList.item(i).getNodeValue().matches("\\s*")) {
System.err.println("このXML文書には、不正な文字列が含まれています");
return;
}
}
}
System.out.println("このXML文書は規定のDTDに従っています");
}
}

