2011-12-29
JavaでXMLを読み込む
Java Advent Calendar 2011 29日目のエントリーです。
以前、XMLの読み込みにJAXB使った事があったんですが
JAXBアンマーシャルでどろんこPart2 - Pastep
それ以外のXMLを取得する機能は使った事が無かったので
この機会に使ってみよう!という事で以下3つについて試して見ましたー。
SAX
public static void main(String[] args) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse("http://search.twitter.com/search.atom?q=インフラエンジニア双六", new DefaultHandler() { private String elementName = null; private StringBuilder name = new StringBuilder(); private StringBuilder title = new StringBuilder(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { elementName = qName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (elementName.equals("name")) { name.append(new String(ch, start, length)); } else if (elementName.equals("title")) { title.append(new String(ch, start, length)); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("entry")) { System.out.println(name.toString() + " : " + title.toString()); name.setLength(0); title.setLength(0); } } }); }
DefaultHandlerを匿名クラスで拡張してパーサーに渡してます。
ハンドラの各メソッドを実装しておけば、XMLで該当の箇所を検出した時にメソッドを実行してくれると。
StAX
public static void main(String[] args) throws Exception { URL url = new URL("http://search.twitter.com/search.atom?q=" + URLEncoder.encode("インフラエンジニア双六", "UTF-8")); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader reader = factory.createXMLStreamReader(connection.getInputStream()); String elementName = null; StringBuilder name = new StringBuilder(); StringBuilder title = new StringBuilder(); while (reader.hasNext()) { switch (reader.next()) { case XMLStreamConstants.START_ELEMENT: elementName = reader.getLocalName(); break; case XMLStreamConstants.CHARACTERS: if (elementName.equals("name")) { name.append(reader.getText()); } else if (elementName.equals("title")) { title.append(reader.getText()); } break; case XMLStreamConstants.END_ELEMENT: if (reader.getLocalName().equals("entry")) { System.out.println(name + " : " + title); name.setLength(0); title.setLength(0); } break; } } connection.disconnect(); }
Iteratorみたいな形でデータを取得出来るのですねー。
処理の主導権がSAXではパーサー側にあるのに対して、StAXでは実行側にある感じ。
EventIteratorAPIというcreateXMLStreamReaderではなく、
createXMLEventReaderで設定する形式もあるみたいですが。
SAXの各メソッド実装をイベントで登録出来るような物なのでしょうかねー…
また、今度試してみたいと思います。
DOM
public static void main(String[] args) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("http://search.twitter.com/search.atom?q=インフラエンジニア双六"); Element rootElement = document.getDocumentElement(); NodeList nodeList = rootElement.getElementsByTagName("entry"); for (int i = 0; i < nodeList.getLength(); i++) { Element element = (Element) nodeList.item(i); String name = element.getElementsByTagName("name").item(0) .getFirstChild().getNodeValue(); String title = element.getElementsByTagName("title").item(0) .getFirstChild().getNodeValue(); System.out.println(name + " : " + title); } }
JavaScriptでエレメントを取得しているのとほぼ同じ形ですねー。
速度とかメモリとか気にしないならこちらが一番わかりやすいかもです。
