解析 XML格式数据
来源:互联网 发布:淘宝客定向计划怎么写 编辑:程序博客网 时间:2024/05/17 02:48
通常情况下,每个需要访问网络的应用程序都会有一个自己的服务器,我们可以向服务 器提交数据,也可以从服务器上获取数据
不过这个时候就出现了一个问题,这些数据到底 要以什么样的格式在网络上传输呢?
在网络上传输数据时最常用的格式有两种,XML和 JSON,今天先学习如何解析 XML格式的数据
在开始之前我们还需要先解决一个问题,就是从哪儿才能获取一段 XML 格式的数据?这里我准备教你搭建一个最简单的 Web服务器,在这个服务器上提供一段 XML文本, 然后我们在程序里去访问这个服务器,再对得到的 XML文本进行解析
1、首先配置apache服务器,可以看以下文章
Apache服务器的下载与安装
2、在htdocs目录下新建get_data.xml文件,文件内容如下
<?xml version="1.0"?><apps> <app> <id>1</id> <name>Google Maps</name> <version>1.0</version> </app> <app> <id>2</id> <name>Chrome</name> <version>2.1</version> </app> <app> <id>3</id> <name>Google Play</name> <version>2.3</version> </app></apps>
ps:如果想要格式化xml文件可以查看这篇文章 [EditPlus格式化XML]
http://blog.csdn.net/u011498933/article/details/53130112
3、现在访问get_data.xml时,页面如下
既然 XML格式的数据已经提供好了,现在要做的就是从中解析出我们想要得到的那部分内容
Pull解析方式
以下代码是基于
HttpURLConnection使用这篇文章进行的修改
只修改MainActivity.java代码
private void sendRequestWithURLConnection() { //开启线程发起网络请求 new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { URL url = new URL("http://192.168.1.51/get_data.xml"); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); InputStream inputStream = connection.getInputStream(); //对获取的输入流进行读取 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } parseXMLWithPull(response.toString()); } catch (MalformedURLException e) { } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } private void parseXMLWithPull(String xmlData) { try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); xmlPullParser.setInput(new StringReader(xmlData)); int eventType = xmlPullParser.getEventType(); String id = ""; String name = ""; String version = ""; while (eventType != XmlPullParser.END_DOCUMENT) { String nodeName = xmlPullParser.getName(); switch (eventType) { case XmlPullParser.START_TAG: //开始解析某个节点 if ("id".equals(nodeName)) { id = xmlPullParser.nextText(); } else if ("name".equals(nodeName)) { name = xmlPullParser.nextText(); } else if ("version".equals(nodeName)) { version = xmlPullParser.nextText(); } break; case XmlPullParser.END_TAG: if("app".equals(nodeName)){ Log.d("MainActivity","id is "+id); Log.d("MainActivity","name is "+name); Log.d("MainActivity","version is "+version); } break; default: break; } eventType = xmlPullParser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
和之前文章相比有两处修改:
1、其中Url变成”http://192.168.1.51/get_data.xml“,http://192.168.1.51对于模拟器来说就是电脑本机的 IP地址,如何查看本机ip地址呢,可以参考以下文章
[查看电脑ip地址]
http://blog.csdn.net/u010356768/article/details/77744688
2、在得到了服务器返回的数据后,我们并不再去发 送一条消息,而是调用了 parseXMLWithPull()方法来解析服务器返回的数据
解释parseXMLWithPull()方法
首先要获取到一个 XmlPullParserFactory 的 实 例 , 并 借 助 这 个 实 例 得 到 XmlPullParser 对象,然后调用 XmlPullParser的 setInput()方法将服务器返回的 XML数据设置进去就可以开始解析了
解析的过程也是非常简单,通过getEventType()可以得到当前的解析事件,然后在一个 while循环 中不断地进行解析
如果当前的解析事件不等于 XmlPullParser.END_DOCUMENT,说明解析工作还没完成,调用 next()方法后可以获取下一个解析事件
在 while循环中,我们通过 getName()方法得到当前结点的名字,如果发现结点名等于 id、name或 version,就调用 nextText()方法来获取结点内具体的内容,每当解析完一个 app 结点后就将获取到的内容打印出来
观察 LogCat中的打印日志
我们已经将 XML数据中的指定内容成功解析出来了
SAX解析方式
SAX解析也是一种特别常 用的 XML解析方式,虽然它的用法比 Pull解析要复杂一些,但在语义方面会更加的清楚
通常情况下我们都会新建一个类继承自 DefaultHandler,并重写父类的五个方法,如下 所示
public class MyHandler extends DefaultHandler { @Override public void startDocument() throws SAXException { super.startDocument(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); } @Override public void endDocument() throws SAXException { super.endDocument(); }}
startDocument()方法会在开始 XML 解析的时候调用
startElement()方法会在开始解析某个结点的时候调用
characters()方法会在获取结点中内容 的时候调用
endElement()方法会在完成解析某个结点的时候调用
endDocument()方法会在 完成整个 XML解析的时候调用
其中,startElement()、characters()和 endElement()这三个方 法是有参数的,从 XML中解析出的数据就会以参数的形式传入到这些方法中。需要注意的 是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容 解析出来,我们需要针对这种情况在代码中做好控制
那么下面就让我们尝试用 SAX解析的方式来实现和上一小节中同样的功能吧
MyHandler
public class MyHandler extends DefaultHandler { private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder version; @Override public void startDocument() throws SAXException { super.startDocument(); id = new StringBuilder(); name = new StringBuilder(); version = new StringBuilder(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); //记录当前节点名 nodeName = localName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); //根据当前的结点名判断将内容添加到哪个StringBulder对象中 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); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if("app".equals(localName)){ Log.d("MyHandler","id is "+id.toString().trim()); Log.d("MyHandler","name is "+name.toString().trim()); Log.d("MyHandler","version is "+version.toString().trim()); //最后把StringBuilder清空 id.setLength(0); name.setLength(0); version.setLength(0); } } @Override public void endDocument() throws SAXException { super.endDocument(); }}
我们首先给 id、name和 version结点分别定义了一个 StringBuilder对象,并 在 startDocument()方法里对它们进行了初始化
每当开始解析某个结点的时候,startElement()方法就会得到调用,其中 localName参数记录着当前结点的名字,这里我们把它记录下来
接着在解析结点中具体内容的时候就会调用 characters()方法,我们会根据当前的结点名进行 判断,将解析出的内容添加到哪一个 StringBuilder对象中
最后在 endElement()方法中进行 判断,如果 app结点已经解析完成,就打印出 id、name和 version的内容
需要注意的是, 目前 id、name和 version中都可能是包括回车或换行符的,因此在打印之前我们还需要调用 一下 trim()方法,并且打印完成后还要将 StringBuilder的内容清空掉,不然的话会影响下一 次内容的读取
接下来的工作就非常简单了,修改 MainActivity中的代码,如下所示:
private void sendRequestWithURLConnection() { //开启线程发起网络请求 new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { URL url = new URL("http://192.168.1.51/get_data.xml"); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); InputStream inputStream = connection.getInputStream(); //对获取的输入流进行读取 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } parseXMLWithSAX(response.toString()); } catch (MalformedURLException e) { } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } private void parseXMLWithSAX(String xmlData){ SAXParserFactory factory = SAXParserFactory.newInstance(); XMLReader xmlReader = null; try { xmlReader = factory.newSAXParser().getXMLReader(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } MyHandler handler = new MyHandler(); //将ContentHandler的实例设置到XMLReader中 xmlReader.setContentHandler(handler); //开始执行解析 try { xmlReader.parse(new InputSource(new StringReader(xmlData))); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } }
在得到了服务器返回的数据后,我们这次去调用 parseXMLWithSAX()方法来解析 XML 数据
parseXMLWithSAX()方法中先是创建了一个 SAXParserFactory的对象,然后再获取到 XMLReader对象,接着将我们编写的 ContentHandler的实例设置到 XMLReader中
最后调 用 parse()方法开始执行解析就好了
现在重新运行一下程序,点击 Send Request按钮后观察 LogCat中的打印日志,你会看 到和Pull方式中解析的一样的结果
- 解析XML格式数据
- 解析XML格式数据
- 解析XML格式数据
- 解析XML格式数据
- 解析XML格式数据
- xml格式数据解析
- 解析XML格式数据
- 解析 XML格式数据
- DOM解析XML格式数据
- Pull解析XML格式数据
- SAX解析XML格式数据
- android解析xml格式数据
- Android 解析XML格式数据
- 解析XML格式的数据
- Java解析xml格式数据
- 解析XML格式数据-Pull解析方式
- 解析XML格式数据--Pull解析
- Android解析数据—XML格式数据
- YARN的服务库和事件库
- Batch Normalization论文读后感
- 莫烦-matplotlib学习笔记(一)
- [花道日常].陈鹳潼.扫描版.pdf 免费下载
- hibernate 的基本原理
- 解析 XML格式数据
- activiti在23张表详解!!!!!!超全
- android进阶篇之View——基础篇
- oracle 表的碎片化整理
- 新路程------hi3516a flashcp 后重启失败
- Springmvc防止重复提交
- JAVA【IO一】IO流
- 各种MATLAB小波基函数
- 【重构练习】大二作业 第3部分