本文共 5020 字,大约阅读时间需要 16 分钟。
网络上传输数据有两种格式:XML 与 JSON。JSON 暂且按下不表,我们先说说如何解析 XML。
1 搭建 Web 服务器
假设我们使用 Apache HTTP Server 搭建好了 Web 服务器(搭建过程请看 )。
我们在 “Apache HTTP Server 安装目录/htdocs” 下,放置一个 XML 文件,文件内容如下:
在浏览器中输入 http://127.0.0.1/data.xml
:
这样就说明 XML 已经成功部署在服务器上咯O(∩_∩)O哈哈~
2 Pull 解析方式
private void sendByOKHttp() { new Thread(new Runnable() { @Override public void run() { OkHttpClient client = new OkHttpClient(); String url = "http://10.0.2.2/data.xml"; Request request = new Request.Builder().url(url).build(); try { Response response = client.newCall(request).execute();//发送请求 String result = response.body().string(); Log.d(TAG, "result: " + result); parseXMLWithPull(result); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
这里我们使用 OkHttp 来提交请求。
注意:因为这里用的是 Android 模拟器,而模拟器本身的 IP 是 127.0.0.1,所以在此不能直接使用,否则会抛出 java.net.ConnectException: Connection refused
异常。我们可以采用 IP 地址 10.0.2.2,它指向的就是本地开发环境。
使用 Pull 方式解析 XML:
private void parseXMLWithPull(String result) { try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); parser.setInput(new StringReader(result)); String id = ""; String name = ""; int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String nodeName = parser.getName(); Log.d(TAG, "nodeName: "+nodeName); switch (eventType) { case XmlPullParser.START_TAG://开始解析 if ("county".equals(nodeName)) { id = parser.getAttributeValue(null, "id"); name = parser.getAttributeValue(null, "name"); } break; case XmlPullParser.END_TAG://完成解析 if ("county".equals(nodeName)) { Log.i(TAG, "id : " + id); Log.i(TAG, "name: " + name); } break; default: break; } eventType=parser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}
在此,我们首先解析 XML 文件,然后把解析得到的数据,打印出来:
3 SAX 解析方式
SAX 解析方式比 Pull 方式要复杂些,但在语义方面会更清楚。
用 SAX 解析需要实现一个继承自 DefaultHandler 的类,并重写父类的 5 个方法。
方法 | 说明 |
---|---|
startDocument() | 在文档开头时,会调用此方法。一般在此做一些预处理的工作。 |
startElement(String namespaceURI, String localName, String qName, Attributes attributes) | 当读取一个开始标签时,会调用此方法。namespaceURI 是命名空间;localName 是不带命名空间前缀的标签名;qName 是带命名空间前缀的标签名; attributes 可以得到所有的属性名和相应的值 。 |
characters(char[] ch, int start, int length) | 这个方法用来处理在 XML 文件中读取到的元素内容。ch 用于存放文件的内容,start 与 length 是读取到的字符串在这个数组中的起始位置和长度,使用 new String(ch,start,length) 就可以获取内容 。 |
endElement(String uri, String localName, String name) | 与 startElement() 方法相对应,解析到结束标签时,会调用该方法。 |
endDocument() | 和 startDocument() 方法相对应。当文档解析结束时,会调用该方法,可以在此做一些善后工作。 |
注意: SAX 是流式处理,即当遇到一个标签时,它并不会纪录下以前所碰到的标签,也就是说,在 startElement() 方法中,所知的只是标签的名字和属性,关于标签的嵌套结构、上层标签,是否有子元素等其它与结构相关的信息并没有记录下来 。 这使得 SAX 在编程处理上没有 DOM 来得方便 。
实现自定义类型解析器:
public class CustomContentHandler extends DefaultHandler { private static final String TAG = "CustomContentHandler"; Listids; List names; @Override public void startDocument() throws SAXException { ids = new ArrayList<>(); names = new ArrayList<>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("county".equals(localName)) { ids.add(attributes.getValue("id")); names.add(attributes.getValue("name")); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { } @Override public void endElement(String uri, String localName, String qName) throws SAXException { } @Override public void endDocument() throws SAXException { Log.i(TAG, "ids : " + ids); Log.i(TAG, "names: " + names); }}
使用 SAX 方式解析 XML:
private void parseXMLWithSAX(String result) { try { SAXParserFactory factory=SAXParserFactory.newInstance(); XMLReader reader=factory.newSAXParser().getXMLReader(); reader.setContentHandler(new CustomContentHandler()); reader.parse(new InputSource(new StringReader(result))); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}
输入结果:
转载地址:https://deniro.blog.csdn.net/article/details/80641583 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!