Archive for 2月, 2005

XMLをJavaで扱う

月曜日, 2月 21st, 2005

SAXとDOM
XMLからデータを読んでDBへ…、という機能を作りました。
JavaでXMLを操作する際は、SAX (Simple API for XML)とDOM(Document Object Model)という標準APIが使えます。オープンソースのXML解析ライブラリもどちらかを使っています。

今回は以下のようなXMLを読込み実験しました。

XML:
  1. <?xml version="1.0" encoding="Shift_JIS" ?>
  2. <root>
  3. <aaa>あいうえお</aaa>
  4. </root>

XMLはW3Cの規約に沿っていないと読み込み時に例外が発生します。
マルチバイト文字の数字とか、括弧とかもです。(意外)

SAXはXML文書を先頭から順に読んでいき、発生したイベント(タグが始まった、終わった等)をアプリケーションでとらえて処理するAPIです。
ノードに階層の深さが決まりきっているXMLを読む際は便利です。
実装はorg.xml.sax.helpers.DefaultHandlerを継承したHandlerクラスを作成します。

JAVA:
  1. package test;
  2.  
  3. import org.xml.sax.*;
  4. import org.xml.sax.helpers.*;
  5.  
  6. public class SampleHandler extends DefaultHandler {
  7.  
  8. public void startDocument() {
  9. //ドキュメント開始
  10. }
  11. public void endDocument() {
  12. //ドキュメント終了
  13. }
  14. /**
  15. * @param namespaceURI
  16. * @param localName
  17. * @param qName
  18. * @param atts
  19. */
  20. public void startElement
  21. (String namespaceURI, String localName, String qName, Attributes atts) {
  22. // 要素の始まりの処理
  23. }
  24. /**
  25. * @param namespaceURI
  26. * @param localName
  27. * @param qName
  28. */
  29. public void endElement(String namespaceURI, String localName, String qName) {
  30. System.out.println("</"+qName+">");
  31. }
  32. public void characters(char[] ch, int start, int length) {
  33. // 要素の間の値
  34. }
  35. }

上で作ったHandlerはこのように使います。

JAVA:
  1. SAXParserFactory factory = SAXParserFactory.newInstance();
  2.  SAXParser parser = factory.newSAXParser();
  3.  String url = "read_test.xml"; // XML文書の実際のURL
  4.  SampleHandler handler = new SampleHandler("a");
  5.  parser.parse(url, handler);// これで解析ができる。

DOMは要素の入れ子階層が不確定なときにwhileなどで使うのに便利です。

JAVA:
  1. package test;
  2.  
  3. import java.io.*;
  4.  
  5. import org.w3c.dom.Document;
  6. import org.w3c.dom.Node;
  7. import javax.xml.parsers.*;
  8.  
  9. /**
  10. * @author nakaya
  11. *
  12. * $Log: $
  13. */
  14. public class NodeSample {
  15.  
  16. private static final String nodeNameText = "#text";
  17. public static void main(String args[]) throws Exception{
  18.    // XMLファイル読込
  19. Document document= DocumentBuilderFactory.newInstance()
  20. .newDocumentBuilder().parse(new File("read_test.xml"));
  21. // ルートノード
  22. Node rootNode = (Node)document.getDocumentElement();
  23.  
  24. // 最初のノード
  25. Node firstNode = rootNode.getFirstChild();
  26. while (null!=firstNode) {
  27. // ノード名
  28. String nodeName = firstNode.getNodeName();
  29. if (nodeName.equals(nodeNameText)) {
  30. firstNode = firstNode.getNextSibling();
  31.     continue;
  32. } else if (nodeName.equals("aaa")) {
  33.     threeNestings(firstNode);
  34. } else if (nodeName.equals("bbb")) {
  35.     threeNestings(firstNode);
  36. }
  37. firstNode = firstNode.getNextSibling();
  38. }
  39. }
  40.  
  41. /**
  42. * 入れ子が2段階
  43. * @param firstNode
  44. */
  45. private static void twoNestings (Node firstNode) {
  46.     Node secondNode = firstNode.getFirstChild();
  47.     while (null!=secondNode) {
  48.     String nodeName2 = secondNode.getNodeName();
  49.     if (!nodeName2.equals(nodeNameText)) {
  50.       System.out.println(nodeName2 + " : "
  51.         + secondNode.getFirstChild().getNodeValue());
  52.     }
  53.    secondNode = secondNode.getNextSibling();
  54. }
  55. }

どちらにせよ、XMLの書式は始めにきっちり決めておいた方が作りやすいのは間違いないですが…。