XMLデータの処理

目的

Apexコードのなかで、XMLを処理する方法をとりあげます。
例として、前回取り上げた、Kakaku.comAPIのデータ取得結果(XML)を処理してみます。

ポイント

XMLを扱うためのApex標準クラスとして、XMLStreamReader/XMLStreamWriterが用意されていますが、これらは比較的低レイヤのAPIのためこれらのクラスをそのまま利用するのは煩雑です。
オープンソースのライブラリとしてXML Dom parserというのがあり、これを使うとXMLのDOM APIを利用できますので、今回はこのXMLDomを使ってみましょう。

XML Dom parser
http://developer.force.com/codeshare/apex/ProjectPage?id=a0630000002ahp5AAA

以下のURLから、XMLDom.clsとXMLDomTest.clsをダウンロードし、各クラスを環境に作成しておきます(現時点でのDeveloper Editionでは、初期状態からXML Domがインストールされています)。
http://code.google.com/p/visualforce-components/source/browse/trunk/XmlDom/src/unpackaged/classes/

サンプルコード

以下のXMLを処理するコードを書いてみます。

<BBSInfo> 
  <ProductID>01309511986</ProductID>
  <NumOfResult>5</NumOfResult>
  <Item> 
    <ThreadTitle>バッテリー消費激しい</ThreadTitle> 
    <ThreadId>9687067</ThreadId> 
    <ThreadClass>0</ThreadClass>
    <ThreadUrl>http://bbs.kakaku.com/bbs/-/SortID=9687067/</ThreadUrl>
    <ThreadSummary>アプリ利用時のバッテリー消費が著しいように思います。バッテリログというアプリを入れて確認したところネット非接続・位置情報サービスオフでも20分程度の使用で残量が20〜30%程度減ります。…</ThreadSummary> 
    <NickName>passatb5</NickName>
    <NumOfResponse>7</NumOfResponse> 
    <WrittenDate>2009/06/12 9:16:43</WrittenDate> 
  </Item> 
  <Item> 
    <ThreadTitle>Mac版ネットブック的な利用をしたいのですが…。</ThreadTitle> 
    <ThreadId>9573279</ThreadId> 
    <ThreadClass>0</ThreadClass>
    <ThreadUrl>http://bbs.kakaku.com/bbs/-/SortID=9573279/</ThreadUrl>
    <ThreadSummary>おはようございます。Mac版ネットブック的な利用をしようと考えて、購入しました。がしかし、自分の使用したい建物が無線LANスポットではないので、上手く活用できません…。ソフトバン…</ThreadSummary> 
    <NickName>ぶっち624</NickName>
    <NumOfResponse>3</NumOfResponse> 
    <WrittenDate>2009/05/20 7:09:16</WrittenDate> 
  </Item> 
</BBSInfo> 

このXMLが文字列変数contentに格納されている場合に、XMLから各要素の情報を取り出すコードです。

public void parseContent(String content){
  // XMLをStringの変数に格納する
  // XMLの文字列を与えて、XMLDomを初期化する
  XMLDom dom  = new XMLDom(content);
  // XMLの中から、Item要素を抽出する(複数返ってくる可能性あり)
  List<XMLDom.Element> items = dom.getElementsByTagName('Item');
  for (XMLDom.Element item:items){
    // item要素の子要素からThreadTitleとThreadIdを取得し、ノード値を取得
    System.out(item.getElementByTagName('ThreadTitle').nodeValue);
    System.out(item.getElementByTagName('ThreadId').nodeValue);
....

制限

現時点で、XML Dom parserは名前空間を無視する作りになっていますので、複数の名前空間を含むXMLを扱う場合には注意が必要です。