Keiichi Oono's Weblog

All | cc | NetBeans | OpenSolaris | Personal
« 前の日(Mar月 17日, 2008年) | 日付別メイン | 次の日(Mar月 19日, 2008年) »
20080319 2008年 3月 19日 水曜日

NetBeans 6.1 Beta, DTD ファイルから DOM ツリースキャナを自動生成させる

前のエントリで紹介した NetBeans 6.1 で復活予定の DTD から DOM ツリースキャナを生成する機能について具体的に見ていきたいと思います。あわせて紹介した SAX ドキュメントハンドラの自動生成については Beta ではうまく動かないので、バグ が修正されてから確認するつもりです。この機能は NetBeans 5.5.1 または NetBeans 6.1 Beta で試すことができます。

使用方法は単純で以下の手順を実行するだけです。

  1. 処理したい XML の DTD を準備
  2. DTD が無い場合には、NetBeans 上で XML ファイルをダブルクリックして「DTD を生成」を実行することもできます
  3. DTD をマウスの右ボタンでクリックして「DOM ツリースキャナを生成」を選択して、クラス名を指定して「了解」をクリックします

例えば、上記の手順で生成されたクラスを使用する主クラスを作れば DOM を使用したパーサーとして使うことができます。

サンプルファイルと実際のコード

サンプルとして次のような XML を定義する、ちょっとしたマシン管理カードのようなもののための DTD を例に使います:

XML の例 (simpletest.xml)

<?xml version="1.0"?>
<!DOCTYPE machine SYSTEM simpletest.dtd">

<machine cpu="UltraSPARC T2" memory="2GB">
  <drive type="HDD" size="300G">
  <dryve type="DVD">
  <peripheral>DAT DDS3</peripheral>
</machine>

上の XML のための DTD (simpletest.dtd)

<xml version="1.0"?>
<!ELEMENT machine (drive*, peripheral*)>
  <!ATTLIST machine cpu CDATA #REQUIRED>
  <!ATTLIST machine memory CDATA #REQUIRED>

<!ELEMENT drive EMPTY>
  <!ATTLIST drive type (HDD | CD | DVD | none) #REQUIRED>
  <!ATTLIST drive size CDATA #IMPLIED>

<!ELELMENT peripheral (#PCDATA)>

上記の simpletest.dtd を右クリックして DOM スキャナを生成させると、デフォルトでは SimpletestScanner.java が生成され、SimpletestScanner クラスには以下のメソッドが実装されます
メソッド名 用途
SimpletestScanner(org.w3c.dom.Document document) コンストラクタ
public void visitDocument() パースして処理する時に呼び出すべきメソッド
void visitElement_drive(org.w3c.dom.Element element) visitDocument() から呼び出される drive 要素用のメソッド
void visitElement_machine(org.w3c.dom.Element element) visitDocument() から呼び出される machine 要素用のメソッド
void visitElement_peripheral(org.w3c.dom.Element element) visitDocument() から呼び出される peripheral 要素用のメソッド

例えば、XML をパースして drive 要素の type 属性の値をプログラムから書き換える必要がある場合には、visitEelement_drive() メソッドに手を加えれば実現します。この例では visitElemnt_drive() は以下のようになっていたので、「ここに処理を追加」と私が追記した部分に必要な処理を書けば OK です。

void visitElement_drive(org.w3c.dom.Element element) {
    // 
// element.getValue();
    org.w3c.dom.NamedNodeMap attrs = element.getAttributes();
    for (int i = 0; i < attrs.getLength(); i++) {
        org.w3c.dom.Attr attr = (org.w3c.dom.Attr) attrs.item(i);
        if (attr.getName().equals("type")) {
            // ここに処理を追加
        }
        if (attr.getName().equals("size")) {
        }
    }
    org.w3c.dom.NodeList nodes = element.getChildNodes();
    for (int i = 0; i < nodes.getLength(); i++) {
...

完成した SimpletestScanner.java を使用するための主クラスは様々な書き方があると思います。一つの例として私が使ったきわめて単純なものを貼り付けておきます。コメントもエラー処理も何もない酷いソースですが、最低限の処理の例と言うことで ...

XML ファイルへのパスを引数として与えると、内容を標準出力に書き出します。StreamResult(System.out)) の部分を StreamResult(new FileOutputStream("/tmp/foo.xml")) などと書き換えるとファイルに出力するようになります。

package xmlsample;

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;

public class RunSimpletestScanner {

    public static void main(String args[]){
        try{
            // 一つめの引数から Document オブジェクトを取得
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dbf.newDocumentBuilder();
            Document doc = builder.parse(new File(args[0]));
  
            // DOM ツリースキャナのインスタンスを取得して visitDocumnent() を呼び出して処理を行う          
            SimpletestScanner scanner = new SimpletestScanner(doc);
            scanner.visitDocument();
            
            // Transformer を準備して、DOM ツリーを標準出力に書き出す
            TransformerFactory tff = TransformerFactory.newInstance();
            Transformer tf = tff.newTransformer();
            tf.transform(new DOMSource(doc), new StreamResult(System.out));
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

 
Posted by keiichio ( 3月 19日 2008年, 02:29:16 午後 JST ) Permalink 投稿されたコメント [0]

Calendar

RSS Feeds

最近の 10 Entries

Links

Navigation

Search