AndroidはXML全攻略を使う(2)


AndroidはXML全攻略を使う(2)
 
Androidは、モバイルデバイスのための新しいオープンソースオペレーティングシステムとSDKである.これにより、強力なモバイルアプリケーションを作成できます.あなたのアプリケーションがWebサービスにアクセスできると、その魅力は大幅に増加します.これはWeb言語:XMLを使用する必要があることを意味します.本論文では、Android上でXMLを使用するさまざまな方法と、それらを使って自分のAndroidアプリケーションを構築する方法を理解します.
 
もっと簡単なSAX解析
Android SDKは、Android.util.Xmlという実用クラスを提供しています.リスト7は、この同じ実用クラスをどのように使用してSAX解像器を設定するかを示している.
リスト7. Android SAX解像器

    
    
    
    
  1. public class AndroidSaxFeedParser extends BaseFeedParser { 
  2. public AndroidSaxFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. RssHandler handler = new RssHandler(); 
  6. try { 
  7. Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, handler); 
  8. catch (Exception e) { 
  9. throw new RuntimeException(e); 
  10. return handler.getMessages(); 
なお、このクラスは標準のSAX処理プログラムを使用していますので、リスト7に示されているRssHandlerだけを再利用しました.SAX処理プログラムを再利用できるのはいいですが、コードがちょっと複雑です.より複雑なXMLドキュメントを解析する必要があると、処理プログラムは様々なバグをもたらす可能性があると考えられます.例えば、リスト6のendElement方法を振り返ってみます.なお、属性設定を試みる前に、currentMessageがnullであるかを確認している.次に、リスト4の例XMLを振り返ってみます.なお、ITEMマークの外部にはTITLEとLINKの表記があります.これがnullを使って検査する原因です.そうでないと、各TITLEマークはNull PointerExceptionをもたらします.Androidは独自のSAX APIを提供しています.(リスト8を参照してください.)あなたが自分のSAX処理プログラムを作成する必要があります.
リスト8. 簡約されたAndroid SAX解像器

    
    
    
    
  1. public class AndroidSaxFeedParser extends BaseFeedParser { 
  2. public AndroidSaxFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. final Message currentMessage = new Message(); 
  6. RootElement root = new RootElement("rss"); 
  7. final List<Message> messages = new ArrayList<Message>(); 
  8. Element channel = root.getChild("channel"); 
  9. Element item = channel.getChild(ITEM); 
  10. item.setEndElementListener(new EndElementListener(){ 
  11. public void end() { 
  12. messages.add(currentMessage.copy()); 
  13. }); 
  14. item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){ 
  15. public void end(String body) { 
  16. currentMessage.setTitle(body); 
  17. }); 
  18. item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){ 
  19. public void end(String body) { 
  20. currentMessage.setLink(body); 
  21. }); 
  22. item.getChild(DESCRIPTION).setEndTextElementListener(new 
  23. EndTextElementListener(){ 
  24. public void end(String body) { 
  25. currentMessage.setDescription(body); 
  26. }); 
  27. item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){ 
  28. public void end(String body) { 
  29. currentMessage.setDate(body); 
  30. }); 
  31. try { 
  32. Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, 
  33. root.getContentHandler()); 
  34. catch (Exception e) { 
  35. throw new RuntimeException(e); 
  36. return messages; 
新しいSAX解析コードはSAX処理プログラムではなく、SDKのAndroid.saxパッケージのクラスを使用しています.これらのクラスは、XMLドキュメントの構造を構築し、必要に応じてイベント傍受プログラムを追加することができます.以上のコードの中で、文書にはrssルートの要素があり、チャンネルのサブ要素があると宣言しました.その後、チャンネルにはITEMのサブ要素があると宣言し、傍受プログラムの追加を開始しました.各傍受プログラムについては、特定のインターフェースを実装した匿名の内部クラスを使用しています.注意してください.文字データを追跡する必要はありません.それだけではなく、もっと簡単になります.もっと重要なのは効率的なことです.最後に、Xml.parseユーティリティを呼び出すと、ルート要素によって生成された処理プログラムが渡されます.
リスト8のコードは全部選択できます.Java環境の標準SAX解析コードに慣れているなら、そのまま使ってもいいです.Android SDKが提供する便利な包装器を試したいなら、それを使ってもいいです.SAXを全く使いたくないなら、どうなりますか?いくつかの代替案が使用できます.その中の第一の方法はDOMです.
DOMを使う
Androidは完全にDOM解析をサポートしています.デスクトップマシンやサーバーでJavaコードを使って実行しているようです.リスト9は、DOMベースの解像度インターフェース実装を示している.
リスト9. DOMベースの構文解析器を実現

    
    
    
    
  1. public class DomFeedParser extends BaseFeedParser { 
  2. protected DomFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
  6. List<Message> messages = new ArrayList<Message>(); 
  7. try { 
  8. DocumentBuilder builder = factory.newDocumentBuilder(); 
  9. Document dom = builder.parse(this.getInputStream()); 
  10. Element root = dom.getDocumentElement(); 
  11. NodeList items = root.getElementsByTagName(ITEM); 
  12. for (int i=0;i<items.getLength();i++){ 
  13. Message message = new Message(); 
  14. Node item = items.item(i); 
  15. NodeList properties = item.getChildNodes(); 
  16. for (int j=0;j<properties.getLength();j++){ 
  17. Node property = properties.item(j); 
  18. String name = property.getNodeName(); 
  19. if (name.equalsIgnoreCase(TITLE)){ 
  20. message.setTitle(property.getFirstChild().getNodeValue()); 
  21. else if (name.equalsIgnoreCase(LINK)){ 
  22. message.setLink(property.getFirstChild().getNodeValue()); 
  23. else if (name.equalsIgnoreCase(DESCRIPTION)){ 
  24. StringBuilder text = new StringBuilder(); 
  25. NodeList chars = property.getChildNodes(); 
  26. for (int k=0;k<chars.getLength();k++){ 
  27. text.append(chars.item(k).getNodeValue()); 
  28. message.setDescription(text.toString()); 
  29. else if (name.equalsIgnoreCase(PUB_DATE)){ 
  30. message.setDate(property.getFirstChild().getNodeValue()); 
  31. messages.add(message); 
  32. catch (Exception e) { 
  33. throw new RuntimeException(e); 
  34. return messages; 
最初のSAX例と同様に、上記のコードはAndroidの場所に全く特定されていない.DOM解析器はすべてのXMLドキュメントをメモリに読み込み、DOM APIを使ってXMLツリーを巡回し、必要なデータを検索することができます.これは非常に直感的なコードであり、いくつかの態様ではSAXベースの実装よりも簡単である.しかし、DOMは通常よりメモリを占有します.すべての内容は先にメモリに読み込まれます.これはAndroidを実行するモバイルデバイスにとって問題ですが、XMLドキュメントは常に小さい時間で実行可能です.これは、Androidの開発者が、SAX解析がAndroidアプリケーション上でより一般的であると考えていることを意味しているので、追加の実用ツールを提供している.Androidはまた、別のタイプのXML解像器を提供しています.これはpull解像器です.
XML pull解析器
前述のように、AndroidはJava StAX APIのサポートを提供していません.しかし、Androidには、StAXのような働き方をするpull解像器がついています.これはあなたのアプリケーションコードが、SAX解析器とは対照的にイベントを処理プログラムに自動的に取り込むことを可能にします.リスト10は、解析インターフェースを提示するpull解像器の実現を示している.
リスト10. Pull解析器による実現

    
    
    
    
  1. public class XmlPullFeedParser extends BaseFeedParser { 
  2. public XmlPullFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. List<Message> messages = null
  6. XmlPullParser parser = Xml.newPullParser(); 
  7. try { 
  8. // auto-detect the encoding from the stream 
  9. parser.setInput(this.getInputStream(), null); 
  10. int eventType = parser.getEventType(); 
  11. Message currentMessage = null
  12. boolean done = false
  13. while (eventType != XmlPullParser.END_DOCUMENT && !done){ 
  14. String name = null
  15. switch (eventType){ 
  16. case XmlPullParser.START_DOCUMENT: 
  17. messages = new ArrayList<Message>(); 
  18. break
  19. case XmlPullParser.START_TAG: 
  20. name = parser.getName(); 
  21. if (name.equalsIgnoreCase(ITEM)){ 
  22. currentMessage = new Message(); 
  23. else if (currentMessage != null){ 
  24. if (name.equalsIgnoreCase(LINK)){ 
  25. currentMessage.setLink(parser.nextText()); 
  26. else if (name.equalsIgnoreCase(DESCRIPTION)){ 
  27. currentMessage.setDescription(parser.nextText()); 
  28. else if (name.equalsIgnoreCase(PUB_DATE)){ 
  29. currentMessage.setDate(parser.nextText()); 
  30. else if (name.equalsIgnoreCase(TITLE)){ 
  31. currentMessage.setTitle(parser.nextText()); 
  32. break
  33. case XmlPullParser.END_TAG: 
  34. name = parser.getName(); 
  35. if (name.equalsIgnoreCase(ITEM) && 
  36. currentMessage != null){ 
  37. messages.add(currentMessage); 
  38. else if (name.equalsIgnoreCase(CHANNEL)){ 
  39. done = true
  40. break
  41. eventType = parser.next(); 
  42. catch (Exception e) { 
  43. throw new RuntimeException(e); 
  44. return messages; 
pull解析器の運転方式はSAX解像器と似ています.これは類似のイベント(開始要素と終了要素)を提供しますが、使用する必要があります.これらを抽出します.イベントは数値コードとして送信されますので、簡単なcase-switchを使ってもいいです.解析はSAX解析のように要素の終了を待つのではなく、開始時に処理がほとんど完了しました.リスト10のコードの中で、ある要素が開始されると、パー.nextText()を呼び出すことができます.XMLドキュメントからすべての文字データを抽出します.また、タグが設定されています.を選択します.XMLドキュメントの読み取りは事前に停止させます.コードがドキュメントの残りの部分に関心を持たないことを知っています.特に、一部のXMLファイルにアクセスするだけで十分に実用的な場合があります.解析時間を大幅に減らすことができます.このような最適化は接続速度の遅い移動に対して非常に有効です.特にアクティブデバイスが重要です.pull解像器は性能の利点と使いやすさを提供できます.XMLの作成にも使えます.
XMLを作成
今までInternetを通じてXMLを解析することに集中していましたが、XMLをリモートサーバに送信する必要がある場合があります.明らかに一つのStringBuiderだけを使ってXML文字列を作成することができます.もう一つの代替方法はリスト11のPull解析器から来ます.
リスト11. pull解析器を使ってXMLを作成する

    
    
    
    
  1. private String writeXml(List<Message> messages){ 
  2. XmlSerializer serializer = Xml.newSerializer(); 
  3. StringWriter writer = new StringWriter(); 
  4. try { 
  5. serializer.setOutput(writer); 
  6. serializer.startDocument("UTF-8"true); 
  7. serializer.startTag("""messages"); 
  8. serializer.attribute("""number", String.valueOf(messages.size())); 
  9. for (Message msg: messages){ 
  10. serializer.startTag("""message"); 
  11. serializer.attribute("""date", msg.getDate()); 
  12. serializer.startTag("""title"); 
  13. serializer.text(msg.getTitle()); 
  14. serializer.endTag("""title"); 
  15. serializer.startTag("""url"); 
  16. serializer.text(msg.getLink().toExternalForm()); 
  17. serializer.endTag("""url"); 
  18. serializer.startTag("""body"); 
  19. serializer.text(msg.getDescription()); 
  20. serializer.endTag("""body"); 
  21. serializer.endTag("""message"); 
  22. serializer.endTag("""messages"); 
  23. serializer.endDocument(); 
  24. return writer.toString(); 
  25. catch (Exception e) { 
  26. throw new RuntimeException(e); 
Xml Serializerクラスは、前の部分で使用されたXml Pull Parsserパッケージの一部です.イベントを抽出していません.データストリームまたは作成プログラムに導入します.この例では、Java.io.StrigWriterの例にイベントをプッシュしただけです.直感的なAPIを提供しています.様々な方法で文書の開始と終了、処理、テキストの追加を行います.またはプロパティです.これはStringBuiderの優れた代替案です.XMLが良い構造を持っていることをより簡単に確認できるからです.
結尾語
Androidデバイスのためにどのような種類のアプリケーションを構築したいですか?いずれにしても、インターネットを通じてデータを使用する必要があるなら、XMLを使用する必要があります.ここでは、AndroidがXMLを処理するためのツールを大量に提供しているのを見ました.その中の一つを自分のツールとして選択することができます.あるいは、ユースケースによって選択することができます.多くの時間ができます.SAXを使うのは比較的安全で、Androidは伝統的なSAXの使い方と便利なSAXの包装器を提供しています.もしあなたの文書が小さいなら、DOMは比較的簡単な方法かもしれません.ドキュメントが大きいなら、文書の一部だけが必要です.XML Pull解析器はもっと有効な方法かもしれません.解像度パケットは便利な方法を提供します.したがって、あなたのXMLの需要にかかわらず、Androidはある程度満足できます.