12.4.2 SAX分析

    为了使用Android上内置的SAX分析器,首先需要创建扩展DefaultHandler的新类。这个类将包含一些方法,可以使用户在启动、停止一个XML元素以及在读取内容时获得通知。下面是一个基本的版本,其仅仅输出日志。

 1     private class UserXMLHandler extends DefaultHandler{
 2         @Override
 3         public void startDocument() throws SAXException {
 4             super.startDocument();
 5             Log.v("SimpleXMLParser", "startDocument");
 6         }
 7         @Override
 8         public void endDocument() throws SAXException {
 9             super.endDocument();
10             Log.v("SimpleXMLParser", "endDocument");
11         }
12         @Override
13         public void startElement(String uri, String localName, String qName,
14                 Attributes attributes) throws SAXException {
15             super.startElement(uri, localName, qName, attributes);
16             Log.v("SimpleXMLParser", "startElement"+localName);
17         }
18         @Override
19         public void endElement(String uri, String localName, String qName)
20                 throws SAXException {
21             super.endElement(uri, localName, qName);
22             Log.v("SimpleXMLParser", "endElement"+localName);
23         }
24         @Override
25         public void characters(char[] ch, int start, int length)
26                 throws SAXException {
27             super.characters(ch, start, length);
28             String stringChars=new String(ch,start,length);
29             Log.v("SimpleXMLParser",stringChars);
30         }
31     }

    一旦获得该类,就可以创建一个SAXParserFactory实例,然后创建一个SAXParser实例。

1         SAXParserFactory aSAXParserFactory=SAXParserFactory.newInstance();
2         SAXParser aSAXParser=aSAXParserFactory.newSAXParser();

    通过SAXParser对象可以得到一个XMLReader,用来确定在分析时会发生什么,并执行实际的分析。

1             XMLReader anXMLReader=aSAXParser.getXMLReader();

    然后实例化XMLHandler,并将它传递给XMLReader上的setContentHandler方法。

1             XMLHandler anUserXMLHandler=new XMLHandler();
2             anXMLReader.setContentHandler(anUserXMLHandler);

    最后调用XMLReader上的parse方法。在当前的情况下,假设有一个称为xmlInputStream的InputStream,其中包含了将要分析的XML。

1             anXMLReader.parse(new InputSource(xmlInputStream));

    下面查看一个完整的示例,其显示了如何分析前述的“用户”XML。

 1 package com.nthm.androidtestActivity;
 2 
 3 import java.io.ByteArrayInputStream;
 4 import java.io.IOException;
 5 import javax.xml.parsers.ParserConfigurationException;
 6 import javax.xml.parsers.SAXParser;
 7 import javax.xml.parsers.SAXParserFactory;
 8 import org.xml.sax.Attributes;
 9 import org.xml.sax.InputSource;
10 import org.xml.sax.SAXException;
11 import org.xml.sax.XMLReader;
12 import org.xml.sax.helpers.DefaultHandler;
13 import android.app.Activity;
14 import android.os.Bundle;
15 import android.util.Log;
16 
17 public class SimpleXMLParser extends Activity {

    需要将XML转换成名为XMLUser的类(在本代码的末尾定义该类)的实例,它将是在XML中定义的数据的java表示。

1     private XMLUser aUser;
2     @Override
3     protected void onCreate(Bundle savedInstanceState) {
4         super.onCreate(savedInstanceState);
5         setContentView(R.layout.main);

    此示例将要分析的XML包含在一个称为xml的字符串中。

1         String xml="<?xml version=\"1.0\"?>\n"
2                     +"<user>\n"
3                     +"<user-id>15</user-id>\n"
4                     +"<username>vanevery</username>\n"
5                     +"<firstname>Shawn</firstname>\n"
6                     +"<lastname>Van Every</lastname>\n"
7                     +"</user>\n";

    下面将依次执行之前所描述的步骤,并创建SAXParserFactory、SAXParser和XMLReader。

1         SAXParserFactory aSAXParserFactory=SAXParserFactory.newInstance();
2         try {
3             SAXParser aSAXParser=aSAXParserFactory.newSAXParser();
4             XMLReader anXMLReader=aSAXParser.getXMLReader();

    然后,将使用下面定义的UserXMLHandler实例作为处理程序,用来确定当分析时会发生的事情。

1             UserXMLHandler aUserXMLHandler=new UserXMLHandler();
2             anXMLReader.setContentHandler(aUserXMLHandler);

    最后将执行实际的分析。必须做一些额外的工作,将位于xml字符串中的XML转换成一个InputStream和一个能够通过XMLReader使用的InputSource。

1             anXMLReader.parse(new InputSource(new ByteArrayInputStream(xml.getBytes())));
2         } catch (ParserConfigurationException e) {
3             e.printStackTrace();
4         } catch (SAXException e) {
5             e.printStackTrace();
6         }catch (IOException e) {
7             e.printStackTrace();
8         }
9     }

    此示例的主要内容是UserXMLHandler。它扩展了DefaultHandler,而且将随着对XML的分析获得它的数据。

1     private class UserXMLHandler extends DefaultHandler{

    我们将使用以下常量并结合state变量来跟踪已经读入了哪些元素。

1         static final int NONE=0;
2         static final int ID=1;
3         static final int FIRSTNAME=2;
4         static final int LASENAME=3;
5         int state=NONE;

    我们将使用以下常量来匹配在XML中可能出现的元素的名称。

1         static final String ID_ELEMENT="user-id";
2         static final String FIRSTNAME_ELEMENT="firstname";
3         static final String LASTNAME_ELEMENT="lastname";

   当分析器确定一个XML文档已经开始时,将调用startDocument方法,在此方法中实例化XMLUser对象,以保存在XML中表示的数据。

1         @Override
2         public void startDocument() throws SAXException {
3             super.startDocument();
4             Log.v("SimpleXMLParser", "startDocument");
5             aUser=new XMLUser();
6         }

    当分析器确定XML文档已经完成时,将调用endDocument方法。此处将只输出XMLUser对象中的内容。

1         @Override
2         public void endDocument() throws SAXException {
3             super.endDocument();
4             Log.v("SimpleXMLParser", "endDocument");
5             Log.v("SimpleXMLParser", "User info:"+aUser.user_id+" "+aUser.firstname+" "+aUser.lastname);
6         }

    当确定了一个新元素开始时,将调用startElement方法。换言之,在XML中发现一个开始标记。将通过localName变量传入该元素的名称。在此方法中只会将该名称与前面定义的常量相比较,并使用它来更改state变量。

 1         @Override
 2         public void startElement(String uri, String localName, String qName,
 3                 Attributes attributes) throws SAXException {
 4             super.startElement(uri, localName, qName, attributes);
 5             Log.v("SimpleXMLParser", "startElement"+localName);
 6             if(localName.equalsIgnoreCase(ID_ELEMENT)){
 7                 state=ID;
 8             }else if(localName.equalsIgnoreCase(FIRSTNAME_ELEMENT)){
 9                 state=FIRSTNAME;
10             }else if(localName.equalsIgnoreCase(LASTNAME_ELEMENT)){
11                 state=LASENAME;
12             }else{
13                 state=NONE;
14             }
15         }

    当发现任何XML结束标记时,将调用endElement方法。

1         @Override
2         public void endElement(String uri, String localName, String qName)
3                 throws SAXException {
4             super.endElement(uri, localName, qName);
5             Log.v("SimpleXMLParser", "endElement"+localName);
6         }

   每当在开始标记和结束标记之间发现文本时,将调用characters方法。在当前实现中将接受数据,并根据state变量表示的再文档中所处的位置将它放入XMLUser对象。

 1         @Override
 2         public void characters(char[] ch, int start, int length)
 3                 throws SAXException {
 4             super.characters(ch, start, length);
 5             String stringChars=new String(ch,start,length);
 6             Log.v("SimpleXMLParser",stringChars);
 7             if(state==ID){
 8                 aUser.user_id+=stringChars.trim();
 9             }else if(state==FIRSTNAME){
10                 aUser.firstname+=stringChars.trim();
11             }else if(state==LASENAME){
12                 aUser.lastname+=stringChars.trim();
13             }
14         }
15     }

    下面是XMLUser类,它用来保存在XML中给定的数据。

 1     class XMLUser{
 2         private String user_id;
 3         private String firstname;
 4         private String lastname;
 5         public XMLUser(){
 6             user_id="";
 7             firstname="";
 8             lastname="";
 9         }
10     }
11 }

    在查看了这个简单的示例之后,可以将它作为在Android上实现任何XML分析的模板,包括处理所接收的用于响应Web服务请求的数据。

posted on 2014-09-11 16:57  宁静致远,一览众山小  阅读(315)  评论(0编辑  收藏  举报

导航