第7回 2007年6月8日 応用Java (Java/XML)
前回までやったこと 「XMLパーサ」-- Java でXMLを処理 javax.xml.stream パッケージのパーサ SAX(Simple API for XML) のパーサ 応用(1) – テーブルの利用 「要素の出現回数を調べる」 応用(2) – フィルタ的な処理
本日(6/8)の講義内容 DOMによる処理 応用:ツリー構造の視覚化 javax.swing.JTree
(復習) パッケージとAPI(1) javax.xml.stream XMLEventReader インタフェース XMLInputFactory クラス javax.xml.stream.events XMLEvent インタフェース サブインタフェース群
(復習) パッケージとAPI(2) SAXParser, SAXParserFactory org.xml.sax javax.xml.parsers SAXParser, SAXParserFactory org.xml.sax XMLReader, InputStream 最も初期から利用可能だったパーサ
パーサを取得するパターン SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser parser = spf.newSAXParser(); XMLReader reader = parser.getXMLReader();
SAXの処理の特徴 XML文書を読み込みながら処理 特定の「節目」でイベントが発生 (イベント駆動型の処理) イベントの処理はHandlerが担当 ContentHandler(のサブクラス) ErrorHandler(のサブクラス)
XMLReaderへのHandlerの登録 XMLReader reader = parser.getXMLReader(); reader.setContentHandler( new MyContentHandler() ); reader.setErrorHandler( new MyErrorHandler() );
その後で、パーシングを開始 XMLReader reader …. : InputSource source = new InputSource( “sample.xml” ); reader.parse( source );
SAXの処理の特徴 XML文書の読み込みと処理が並行に進行 要素(タグ)ごとに逐次処理 読み込みと処理は同時に終了 (後処理には別の機構が必要)
ContentHandler の主要な仕事 startDocument() – パーシングの開始時 endDocument() – パーシングの終了時 startElement() – 要素(タグ)の開始 endElement() – 要素(タグ)の終了 characters() – 平文テキストの読み込み
ErrorHandlerの仕事 3つのエラーレベル fatalError 文書名の間違い、不存在 XML文書として不適切(文法エラー) warning エラーではない不適切な記述
DOMによる処理 DOM(Document Object Model ) 文書の構造を記述(DOMツリー)
パーサの取得のパターン DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder();
DOMの処理の特徴 XML文書の一括読み込み (処理は読み込み完了後) XML文書の構造をツリーとしてメモリ上に記憶
DOM と SAXとの比較 処理の手順 SAX:文書の頭から逐次処理 DOM:一括読み込み後ランダムアクセス 適した用途 システムへの負荷 SAX:比較的低い DOM:メモリ必要
DOMツリーの表現 org.w3c.dom.Node インタフェース 主要な Node のサブインタフェース Document Element Attr Text
XML文書の構造の例 <document> <title>Java and XML</title> Let's begin, now! <image source="java.png" width="512" height="400"/> </document>
DOMツリーによる表現
ノードとしての性質 階層構造(親子関係) getParentNode() getChildNodes() 再帰的呼び出しによる処理
再帰的な呼び出しの例 public void printNode( Node node ) { NodeList list = node.getChildNodes(); if( list.getLength() == 0 ) return; for( int i=0; i<list.getLength(); i++ ) { printNode( list.item(i)); }
XMLにおける「属性(Attribute)」 要素の開始タグ内部に記述 個数は任意、出現順序は意味を持たない 「名前(name)」と「値(value)」のペアの集まり <image source=“java.png” width=“200” height=“300”></image>
属性(Attribute)の扱い 属性も Nodeのサブインタフェース Attr 属性の取り出しには Nodeの集合 NamedNodeMap 重複しない名前を指定 インデックス番号による管理
属性を扱う例(1) if( node.getNodeType() == Node.ELEMENT_NODE ) { NamedNodeMap nnp = node.getAttributes(); }
属性を扱う例(2) for( int i=0; i<nnp.getLength(); i++ ) { Node n = nnp.item( i ); if( n.getNodeType() == Node.ATTRIBUTE_NODE ) { Attr a = (Attr)n; System.out.print( "[" + a.getName() + "=" + a.getValue() + "]" ); }
補足 NamedNodeMap の要素は一般に Node (形式上は Attr のみが対象ではない) getAttributes()メソッドは Nodeで定義 (しかし、Element以外では無意味) 他の属性を扱うメソッドはElementで定義 getAttribute(), setAttribute()
ツリーの視覚化とSwing javax.swing.JTree クラス javax.swing.tree パッケージ DefaultMutableTreeNode クラス javax.swing.event パッケージ
DOMツリーの視覚化(1) dbf =DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); Document doc = db.parse( source ); Node rootTag = doc.getFirstChild(); root = newDefaultMutableTreeNode( rootTag.getNodeName() ); tree = new JTree( root ); addToTree( rootTag, root );
DOMツリーの視覚化(2) public void addToTree( Node node, DefaultMutableTreeNode branch ) { : DefaultMutableTreeNode tn = new DefaultMutableTreeNode( child.getNodeName() ); branch.add( tn ); addChildren( child, tn );