Android--SAX解析方式

来源:互联网 发布:linux读取文件循环 编辑:程序博客网 时间:2024/06/05 18:32
Pull 解析方式虽然非常的好用,但它并不是我们唯一的选择。SAX解析也是一种特别常
用的 XML 解析方式,虽然它的用法比 Pull解析要复杂一些,但在语义方面会更加的清楚。
通常情况下我们都会新建一个类继承自 DefaultHandler,并重写父类的五个方法,如下

所示:

public class MyHandler extends DefaultHandler {@Overridepublic void startDocument() throws SAXException {}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {}@Overridepublic void characters(char[] ch, int start, int length) throwsSAXException {}@Overridepublic void endElement(String uri, String localName, String qName) throwsSAXException {}@Overridepublic void endDocument() throws SAXException {}}

这五个方法一看就很清楚吧?startDocument()方法会在开始 XML 解析的时候调用,
startElement()方法会在开始解析某个结点的时候调用,characters()方法会在获取结点中内容
的时候调用,endElement()方法会在完成解析某个结点的时候调用,endDocument()方法会在
完成整个 XML 解析的时候调用。其中,startElement()、characters()和 endElement()这三个方
法是有参数的,从 XML 中解析出的数据就会以参数的形式传入到这些方法中。需要注意的
是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容
解析出来,我们需要针对这种情况在代码中做好控制。
那么下面就让我们尝试用 SAX 解析的方式来实现和上一小节中同样的功能吧。新建一
个 ContentHandler类继承自 DefaultHandler,并重写父类的五个方法,如下所示:

public class ContentHandler extends DefaultHandler {private String nodeName;private StringBuilder id;private StringBuilder name;private StringBuilder version;@Overridepublic void startDocument() throws SAXException {id = new StringBuilder();name = new StringBuilder();version = new StringBuilder();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// 记录当前结点名nodeName = localName;}@Overridepublic void characters(char[] ch, int start, int length) throwsSAXException {// 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中if ("id".equals(nodeName)) {id.append(ch, start, length);} else if ("name".equals(nodeName)) {name.append(ch, start, length);} else if ("version".equals(nodeName)) {version.append(ch, start, length);}}@Overridepublic void endElement(String uri, String localName, String qName) throwsSAXException {if ("app".equals(localName)) {Log.d("ContentHandler", "id is " + id.toString().trim());Log.d("ContentHandler", "name is " + name.toString().trim());Log.d("ContentHandler", "version is " + version.toString().trim());// 最后要将StringBuilder清空掉id.setLength(0);name.setLength(0);version.setLength(0);}}@Overridepublic void endDocument() throws SAXException {}}

可以看到,我们首先给 id、name 和 version 结点分别定义了一个 StringBuilder 对象,并
在 startDocument()方法里对它们进行了初始化。 每当开始解析某个结点的时候, startElement()
方法就会得到调用,其中 localName 参数记录着当前结点的名字,这里我们把它记录下来。
接着在解析结点中具体内容的时候就会调用 characters()方法, 我们会根据当前的结点名进行
判断,将解析出的内容添加到哪一个 StringBuilder对象中。最后在 endElement()方法中进行
判断,如果 app结点已经解析完成,就打印出 id、name 和 version的内容。需要注意的是,
目前 id、name 和 version中都可能是包括回车或换行符的,因此在打印之前我们还需要调用
一下 trim()方法,并且打印完成后还要将 StringBuilder的内容清空掉,不然的话会影响下一
次内容的读取。
接下来的工作就非常简单了,修改 MainActivity中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {……private void sendRequestWithHttpClient() {new Thread(new Runnable() {@Overridepublic void run() {try {HttpClient httpClient = new DefaultHttpClient();// 指定访问的服务器地址是电脑本机HttpGet httpGet = new HttpGet("http://10.0.2.2:8080/get_data.xml");HttpResponse httpResponse = httpClient.execute(httpGet);if (httpResponse.getStatusLine().getStatusCode() == 200) {// 请求和响应都成功了HttpEntity entity = httpResponse.getEntity();String response = EntityUtils.toString(entity,"utf-8");parseXMLWithSAX(response);}} catch (Exception e) {e.printStackTrace();}}}).start();}……private void parseXMLWithSAX(String xmlData) {try {SAXParserFactory factory = SAXParserFactory.newInstance();XMLReader xmlReader = factory.newSAXParser().getXMLReader();ContentHandler handler = new ContentHandler();// 将ContentHandler的实例设置到XMLReader中xmlReader.setContentHandler(handler);// 开始执行解析xmlReader.parse(new InputSource(new StringReader(xmlData)));} catch (Exception e) {e.printStackTrace();}}}

在得到了服务器返回的数据后,我们这次去调用 parseXMLWithSAX()方法来解析 XML
数据。parseXMLWithSAX()方法中先是创建了一个 SAXParserFactory的对象,然后再获取到
XMLReader对象,接着将我们编写的 ContentHandler的实例设置到 XMLReader中,最后调
用 parse()方法开始执行解析就好了。
现在重新运行一下程序,点击 Send Request 按钮后观察 LogCat 中的打印日志,你会看
到和图 10.7中一样的结果。
除了 Pull 解析和 SAX 解析之外,其实还有一种 DOM 解析方式也算挺常用的,不过这
里我们就不再展开进行讲解了,感兴趣的话你可以自己去查阅一下相关资料。

1 0
原创粉丝点击