Adroid开发之解析xml数据的两种方式

前端之家收集整理的这篇文章主要介绍了Adroid开发之解析xml数据的两种方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

在android开发中,从服务器拿到的xml数据存在两种解析方式:

  • Pull解析方式
  • SAX解析方式

接下来我们来一一说一下具体用法
这里为了测试,我们首先在测试服务器上放上一个get_date.xml文件,以方便我们终端来请求解析。文件内容如下:

1.Pull解析方式

代码如下:

  1. @Override
  2. public void onClick(View v) {
  3. switch (v.getId()) {
  4. case R.id.send_req:
  5. sendRequestWithHttpClient();
  6. break;
  7.  
  8. default:
  9. break;
  10. }
  11. }
  12.  
  13. // The code that request is Success
  14. private static final int REQUEST_SUCCESS = 200;
  15.  
  16. // Encoding format
  17. private static final String UTF_8 = "UTF-8";
  18.  
  19. /** * HttpClient * * The HttpClient was supported by Apache * */
  20. private void sendRequestWithHttpClient() {
  21.  
  22. new Thread(new Runnable() {
  23.  
  24. @Override
  25. public void run() {
  26. // this is a GET request
  27. try {
  28. HttpClient httpClient = new DefaultHttpClient();
  29. HttpGet httpGet = new HttpGet("http://127.0.0.1/get_data.xml");
  30. HttpResponse httpResponse = httpClient.execute(httpGet);
  31.  
  32. if (httpResponse.getStatusLine().getStatusCode() == REQUEST_SUCCESS) {
  33. HttpEntity entity = httpResponse.getEntity();
  34. String response = EntityUtils.toString(entity,UTF_8);
  35.  
  36. // Parse xml data by Pull method
  37. parseXMLWithPull(response);
  38.  
  39. }
  40. } catch (Exception e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }).start();
  45.  
  46.  
  47. }
  48.  
  49. /** * parse XML data by Pull method * * @param xmlData */
  50. private void parseXMLWithPull(String xmlData) {
  51. try {
  52. XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
  53. XmlPullParser xmlPullParser = factory.newPullParser();
  54. xmlPullParser.setInput(new StringReader(xmlData));
  55.  
  56. int eventType = xmlPullParser.getEventType();
  57.  
  58. String id = "";
  59. String name = "";
  60. String version = "";
  61. while (eventType != XmlPullParser.END_DOCUMENT) {
  62. String nodeName = xmlPullParser.getName();
  63. switch (eventType) {
  64. // Begin to parse a tag
  65. case XmlPullParser.START_TAG:
  66. if ("id".equals(nodeName)) {
  67. id = xmlPullParser.nextText();
  68. } else if ("name".equals(nodeName)) {
  69. name = xmlPullParser.nextText();
  70. } else if ("version".equals(nodeName)) {
  71. version = xmlPullParser.nextText();
  72. }
  73. break;
  74.  
  75. // When we parsed a tag,print the infos
  76. case XmlPullParser.END_TAG:
  77. if ("app".equals(nodeName)) {
  78. Log.d("Info","id is " + id);
  79. Log.d("Info","name is " + name);
  80. Log.d("Info","version is " + version);
  81. }
  82. break;
  83. default:
  84. break;
  85. }
  86. }
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. }
  90. }

这里首先要获取到一个XmlPullParserFactory 的 实 例 , 并 借 助 这 个 实 例 得 到 XmlPullParser 对 象 , 然 后 调 用
XmlPullParser 的 setInput()方法将服务器返回的 XML 数据设置进去就可以开始解析了。解析的过程也是非常简单,通过 getEventType()可以得到当前的解析事件,然后在一个 while 循环中不断地进行解析,如果当前的解析事件不等于 XmlPullParser.END_DOCUMENT,说明解析工作还没完成,调用 next()方法后可以获取下一个解析事件。在 while 循环中,我们通过 getName()方法得到当前结点的名字,如果发现结点名等于id、name 或 version,就调用 nextText()方法获取结点内具体的内容,每当解析完一个 app结点后就将获取到的内容打印出来。

打印结果:

2.SAX解析方式

除了Pull方式来解析外,我们还可以用SAX方式来解析,用法上比Pull方式稍微复杂一些,但是语义方面更加清晰。
通常情况下我们都会新建一个类继承自 DefaultHandler,并重写父类的五个方法,如下所示:

这里说明一下上面几个方法的用处:

  • startDocument() : 开始 XML 解析的时候调用
  • startElement() : 开始解析某个结点的时候调用
  • characters() : 在获取结点中内容的时候调用
  • endElement() : 在完成解析某个结点的时候调用
  • endDocument() : 在完成整个 XML 解析的时候调用

其中,startElement()、characters()和 endElement()这三个方法是有参数的,从 XML 中解析出的数据就会以参数的形式传入到这些方法中。需要注意的是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容解析出来,我们需要针对这种情况在代码中做好控制。

接下来,我们来看看具体应用代码

  1. import org.xml.sax.Attributes;
  2. import org.xml.sax.SAXException;
  3. import org.xml.sax.helpers.DefaultHandler;
  4.  
  5. import android.util.Log;
  6.  
  7. /** * 解析xml * */
  8. public class ContentHandler extends DefaultHandler {
  9.  
  10. private String nodeName;
  11.  
  12. private StringBuilder id;
  13.  
  14. private StringBuilder name;
  15.  
  16. private StringBuilder version;
  17.  
  18. @Override
  19. public void startDocument() throws SAXException {
  20. id = new StringBuilder();
  21. name = new StringBuilder();
  22. version = new StringBuilder();
  23. }
  24.  
  25. @Override
  26. public void endDocument() throws SAXException {}
  27.  
  28. @Override
  29. public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
  30. // 记录当前节点名
  31. nodeName = localName;
  32. }
  33.  
  34. @Override
  35. public void endElement(String uri,String qName)
  36. throws SAXException {
  37. if ("app".equals(localName)) {
  38. Log.d("ContentHandler","id is " + id.toString().trim());
  39. Log.d("ContentHandler","name is " + name.toString().trim());
  40. Log.d("ContentHandler","version is " + version.toString().trim());
  41.  
  42. // 最后将StringBuilder清空掉
  43. id.setLength(0);
  44. name.setLength(0);
  45. version.setLength(0);
  46. }
  47. }
  48.  
  49. @Override
  50. public void characters(char[] ch,int start,int length)
  51. throws SAXException {
  52. // 根据当前的节点名判断将内容添加到哪一个StringBuilder中
  53. if ("id".equals(nodeName)) {
  54. id.append(ch,start,length);
  55. } else if ("name".equals(nodeName)) {
  56. name.append(ch,length);
  57. } else if ("version".equals(nodeName)) {
  58. version.append(ch,length);
  59. }
  60. }
  61.  
  62.  
  63. }

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

修改MainActivity.java中的代码

  1. /** * HttpClient * * The HttpClient was supported by Apache * */
  2. private void sendRequestWithHttpClient() {
  3.  
  4. new Thread(new Runnable() {
  5.  
  6. @Override
  7. public void run() {
  8. // this is a GET request
  9. try {
  10. HttpClient httpClient = new DefaultHttpClient();
  11. HttpGet httpGet = new HttpGet("http://127.0.0.1/get_data.xml");
  12. HttpResponse httpResponse = httpClient.execute(httpGet);
  13.  
  14. if (httpResponse.getStatusLine().getStatusCode() == REQUEST_SUCCESS) {
  15. HttpEntity entity = httpResponse.getEntity();
  16. String response = EntityUtils.toString(entity,UTF_8);
  17.  
  18. // Parse xml data by SAX method
  19. parseXMLWithSAX(response);
  20.  
  21. }
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }).start();
  27.  
  28.  
  29. }
  30.  
  31. /** * pares XML data by SAX method * * @param xmlData */
  32. private void parseXMLWithSAX(String xmlData) {
  33. try {
  34. SAXParserFactory factory = SAXParserFactory.newInstance();
  35. XMLReader reader = factory.newSAXParser().getXMLReader();
  36. ContentHandler handler = new ContentHandler();
  37. // 将contentHandler实例设置到reader中
  38. reader.setContentHandler(handler);
  39. // 开始解析
  40. reader.parse(new InputSource(new StringReader(xmlData)));
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. }
  44.  
  45. }

除了上述两种解析方式外,还有一种DOM解析,这里后面再补上…

猜你在找的XML相关文章