说说在 Android 中如何解析 XML

网络上传输数据有两种格式:XML 与 JSON。JSON 暂且按下不表,我们先说说如何解析 XML。

1 搭建 Web 服务器

假设我们使用 Apache HTTP Server 搭建好了 Web 服务器(搭建过程请看 这里)。

我们在 "Apache HTTP Server 安装目录/htdocs" 下,放置一个 XML 文件,文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>  
  
<China>  
  <province id="01" name="北京">  
    <city id="0101" name="北京">  
      <county id="010101" name="北京" weatherCode="101010100"/>  
      <county id="010102" name="海淀" weatherCode="101010200"/>  
      <county id="010103" name="朝阳" weatherCode="101010300"/>  
      <county id="010104" name="顺义" weatherCode="101010400"/>  
      <county id="010105" name="怀柔" weatherCode="101010500"/>  
      <county id="010106" name="通州" weatherCode="101010600"/>  
      <county id="010107" name="昌平" weatherCode="101010700"/>  
      <county id="010108" name="延庆" weatherCode="101010800"/>  
      <county id="010109" name="丰台" weatherCode="101010900"/>  
      <county id="010110" name="石景山" weatherCode="101011000"/>  
      <county id="010111" name="大兴" weatherCode="101011100"/>  
      <county id="010112" name="房山" weatherCode="101011200"/>  
      <county id="010113" name="密云" weatherCode="101011300"/>  
      <county id="010114" name="门头沟" weatherCode="101011400"/>  
      <county id="010115" name="平谷" weatherCode="101011500"/>  
    </city>  
  </province>  
</China>

在浏览器中输入 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";

    List<String> ids;
    List<String> 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();
    }
}

输入结果:

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,469评论 19 139
  • 一、绪论 上周工作需要了解项目的一些大体内容,结果在xml解析这一块看的迷迷糊糊的,所以在这里把学习到xm...
    cao健强阅读 9,604评论 1 7
  • 1. XML总结 1.1. XML简介 XML : 可扩展的标记语言。(和HTML非常类似的) 可扩展的。 自定义...
    Ethan_Walker阅读 8,428评论 0 12
  • “嗨,妈妈”电话那头,儿子的声音洋溢着兴奋,“嗨,宝贝,今天该去一年级上课了,高兴吗?”“高兴呀!”“那就好,等你...
    小鹿says阅读 2,578评论 0 2
  • 1 沈从文先生在他的《湘行散记》中说:我行过许多地方的桥,看过许多次数的云,喝过许多种类的酒,却只爱过一个正当最好...
    小苜蓿阅读 5,114评论 20 11