RSSをSAXで読み込むプログラムを作ります。
org.xml.saxは、JDKに標準で入っている、 XMLをJavaプログラムから処理する為のフレームワークです。 SAX(Simple API for Xml)では、XML文書を読み込んでいる時に イベントが発生します。 発生したイベントはイベントハンドラで処理します。
SAXParserFactory spfactory = SAXParserFactory.newInstance(); SAXParser parser = spfactory.newSAXParser(); parser.parse(new File( XMLファイル名 ), ハンドラ );
SAXのイベントを処理するハンドラは、DefaultHandler?を継承して、 イベント発生時に動くメソッドをオーバーライドします。
タグの開始イベントで返されるorg.xml.sax.Attributesを解析することによってタグ属性を解析することができます。
タグの開始イベント(startElement())で、タグ名をスタックにつんで、
タグの終了イベント(endElement())で、タグ名をスタックから引き出します。
そしてタグに挟まれた要素発見のイベント(character())では、スタックを参照して現在位置を調べて、対応する処理を行います。
public class RSSSAXReader extends DefaultHandler { // タグのスタック Stack tagStack = new Stack(); public static void main(String[] args) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setValidating(true); org.xml.sax.XMLReader reader = spf.newSAXParser().getXMLReader(); reader.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); reader.setContentHandler(new RSSSAXReader()); reader.setErrorHandler(new ParseErrorHandler()); reader.parse(new InputSource(System.in)); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } } public void startDocument() { System.out.println(" ==▼=====ドキュメント開始イベント"); } public void endDocument() { System.out.println(" ==▲=====ドキュメント終了イベント"); } public void startElement( String uri, String localName, String qName, Attributes attributes) { System.out.println(" " + tagStack + ":" + "▽タグ開始イベント"); System.out.println( " " + tagStack + ":" + "--タグ属性=" + getAttrMap(attributes)); tagStack.push(qName); } public void characters(char[] ch, int offset, int length) { // 注意:このままのコードでは取りこぼしあり!次章に解決策あり System.out.println( " " + tagStack + ":" + (new String(ch, offset, length)).trim()); } public void endElement(String uri, String localName, String qName) { System.out.println(" " + tagStack + ":" + "△タグ終了イベント"); tagStack.pop(); } public Map getAttrMap(Attributes attributes) { Map attrMap = new HashMap(); int length = attributes.getLength(); for (int cnt = 0; cnt < length; cnt++) { attrMap.put(attributes.getQName(cnt), attributes.getValue(cnt)); } return attrMap; } }
パーサは、このメソッドを呼び出して、各文字データチャンクを報告します。 SAX パーサは、連続する文字データを単一のチャンクとして、 またはいくつかのチャンクに分割して返します。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^となっています。
<parent> <name>よたろう</name> <child> <name>じゅげむじゅげむごこうのすりきれかいじゃりすいぎょのすいぎょうまつ うんらいまつふうらいまつくうねるところにすむところやぶらこうじのぶらこうじ ぱいぽぱいぽぱいぽのしゅーりんがんしゅーりんがんのぐーりんだいぐーりんだいの ぽんぽこぴーのぽんぽこなーのちょうきゅうめいのちょうすけ</name> </child> </parent>を読み込むと以下のようにイベントが発生する可能性があるということ
01 startDocument() 02 startElement(parent) 03 startElement(name) 04 characters(よたろう) 05 endElement(name) 06 startElement(child) 07 startElement(name) 08 characters(じゅげむじゅげむ) 09 characters(ごこうのすりきれ) … 95 characters(ちょうすけ) 96 endElement(name) 97 endElement(child) 98 endElement(parent) 99 endDocument()
public class NewRSSSAXReader extends DefaultHandler { // タグのスタック Stack tagStack = new Stack(); // Elementの格納場所 StringBuffer leaf = null; public void startElement( leaf = new StringBuffer(); tagStack.push(qName); } public void characters(char[] ch, int offset, int length) { if( leaf != null ){ leaf.append( new String(ch, offset, length) ); } } public void endElement(String uri, String localName, String qName) { if( leaf != null ){ System.out.println( tagStack + ":" + leaf.toString().trim() ); leaf = null; } tagStack.pop(); } }
</child> (改行) </parent> ↑ ココでcharacter()イベントが発生