import java.io.*;
import java.net.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
// XML DOM Tree を表示するプログラム
// 使い方: java DocumentTreeViewer url [encoding]
// (encoding は指定しないと utf-8)
public class DocumentTreeViewer {
public static void main(String[] args) {
String encoding = "utf-8"; // 文字コードの初期値は utf-8
if(args.length > 1) // 第2引数があったらそれを文字コードとして指定
encoding = args[1];
// Document Tree を生成 (URL, 文字コードを指定)
DocumentTree tree = new DocumentTree(args[0], encoding);
// Tree を表示
tree.show();
}
}
// XML DOM Tree を表すクラス
class DocumentTree {
private Document document;
private int depth; // 階層
public DocumentTree(String urlString, String encoding) {
document = null;
try {
// まずは接続し、データを読む Reader を生成
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,
encoding);
BufferedReader in = new BufferedReader(reader);
// Reader を使ってストリームを読み、それを解析して Document を生成
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(new InputSource(in));
in.close();
}
catch (ParserConfigurationException e) {
System.err.println("DocumentBuilderFactory生成エラー:" + e);
}
catch (SAXException e) {
System.err.println("構文エラー:" + e);
}
catch (IOException e) {
System.err.println("入出力エラー:" + e);
}
}
/** DOM Tree の内容を表示 */
public void show() {
depth = 0;
try {
// root 要素を与えて showTree を呼び出す
showTree(document.getDocumentElement());
}
catch (DOMException e) {
System.err.println("DOMエラー:" + e);
}
}
/** 引数 node 以下の tree を表示 */
private void showTree(Node node) {
for(Node current = node.getFirstChild();
current != null;
current = current.getNextSibling()) {
if(current.getNodeType() == Node.ELEMENT_NODE) { // ノードは要素?
String nodeName = current.getNodeName();
// 中括弧 { } を使って階層の深さを表現
System.out.println(indent() + nodeName + " {");
depth++;
showTree(current); // さらに子ノードを見る (再帰)
depth--;
System.out.println(indent() + "}");
}
else if(current.getNodeType() == Node.TEXT_NODE // ノードはテキスト?
&& current.getNodeValue().trim().length() != 0)
System.out.println(indent() + current.getNodeValue());
else if(current.getNodeType() == Node.CDATA_SECTION_NODE) // ノードはCDATA?
System.out.println(indent() + current.getNodeValue());
// HTMLタグなどを含む
; // 上記以外のノードでは何もしない
}
}
// 階層 depth にあわせた字下げ用の空白を生成
private String indent() {
String indent = "";
for(int i = 0; i < depth; i++)
indent += " ";
return indent;
}
}