为了使用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"?> " 2 +"<user> " 3 +"<user-id>15</user-id> " 4 +"<username>vanevery</username> " 5 +"<firstname>Shawn</firstname> " 6 +"<lastname>Van Every</lastname> " 7 +"</user> ";
下面将依次执行之前所描述的步骤,并创建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服务请求的数据。