Android中常见的XML解析方式

基本概念

  1. 概念:extensive markup language(可扩展的标记语言)
    XML是一种通用的数据存储和交换格式,与平台无关,与编程语言无关,与操作系统无关。给数据集成和交互提供了极大的便利。
    将数据格式化成XML文件后,真正实现了数据跨平台的交互和共享。在不同语言中,xml的解析方式都一样。

  2. XML文件格式
    1.每个xml文件中要有一个,且只能有一个xml根节点;
    2.xml文件的数据中不可以 出现”< “或者” >”;

  3. XML的解析方式
    DOM(document object model :文档对象模型):借助文档树模型对xml文档进行分析。
    SAX(simple API for xml :xml的简单api):利用事件流的形式解析XML
    PULL:利用事件流模型来解析XML。
    备注:DOM和SAX解析的优劣分析:DOM是将文档一次性读入到内存,然后以文档树模进行分析节点信息。获取到希望获取的数据;
    而SAX是事件流的形式去分析xml文件。DOM可以做到对文档中部分节点的修改、删除和新增,而SAX无法做到。

PULL解析xml

  1. PULL Parser中的几种event值
    1、START_DOCUMENT: 0
    2、END_DOCUMENT: 1
    3、START_TAG: 2
    4、END_TAG: 3
    5、TEXT: 4

  2. 核心类:
    XmlPullParserFactory
    XmlPullParser

  3. 核心代码:

    // 实例化一个xml pull解析的工厂
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    // 实例化一个xml pull解析对象
    XmlPullParser parser = factory.newPullParser();
    // xml解析对象接收输入流对象
    parser.setInput(instream, "utf-8");
    int event = parser.getEventType();//获取事件类型
    while (event != XmlPullParser.END_DOCUMENT) {
    switch (event) {
     case XmlPullParser.START_DOCUMENT:
           //开始读取文档
        break;
     case XmlPullParser.START_TAG:
          //读取元素开始标签
        break;
     case XmlPullParser.TEXT:
          //读取文本
       break;
     case XmlPullParser.END_TAG:
          //读取闭合标签
       break;
    }
    event = parser.next();//获取下一次解析事件
    }
  4. 常用api

 //获取属性名
 parser.getAttributeName()
 //获取属性值
 parser.getAttributeValue()
 //获取文本值
 parser.getText();
 //获取标签名
 parser.getName();
 //获取下一个文本解析事件,返回文本值(如果当前是START_TAG,且下一个节点是TEXT,则返回文本,如果下一个是END_TAG,返回null,否则则会抛出异常)
 parser.nextText();
 //获取下一个标签解析事件,返回事件类型,如果下一个事件不是START_TAG或END_TAG,则抛出异常
 parser.nextTag();
 //获取下一个解析事件,返回事件类型
 parser.next();

SAX解析xml

SAX解析基本与PULL解析基本相同,也是通过事件流的形式解析xml,SAX的解析借助于DefaultHandler这个处理类。该类实现如下:


     class MyXmlHandler extends DefaultHandler {

         /** * 开始读取文档 * * @throws SAXException */
         @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);
             //uri:命名空间
             //localName:不带前缀(命名空间)的标签名
             //qName:带前缀的标签名
             //attributes:属性集合

         }

         /** * 开始读取Text */
         @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);
             //uri:命名空间
             //localName:不带前缀(命名空间)的标签名
             //qName:带前缀的标签名
         }

         /** * 结束读取文档 */
         @Override
         public void endDocument() throws SAXException {
             super.endDocument();
         }
     }

核心代码如下:

 SAXParserFactory factory=SAXParserFactory.newInstance();
 SAXParser parser=factory.newSAXParser();
 MyXmlHandler handler=new MyXmlHandler();//继承自DefaultHandler
 parser.parse(in,handler);//插入一个自定义的xml处理器

DOM解析xml

  1. DOM树中对节点(NODE)的分类如下
    1、文档节点,Document
    2、元素节点,Element
    3、属性节点,Attribute
    4、文本节点,Text
    5、注释节点,Comment

  2. 核心类:
    DocumentBuilderFactory
    DocumentBuilder
    Doucment,一个xml就是一个Document
    Element ,…就是一个元素
    NodeList ,节点集合
    Node,节点,包括文档、元素、属性、文本节点等

  3. 核心代码

    DocumentBuilderFactory factory =  DocumentBuilderFactory.newInstance();
    // 使用工厂来实例化一个构造Document的对象
    DocumentBuilder builder = factory.newDocumentBuilder();
    // 利用DocumentBuilder来构造一个Document对象
    Document document = builder.parse(filename);
    // 获取Document文档的根节点对象
    Element root = document.getDocumentElement();
    // 通过根节点,获取到根节点下面的所有二级子节点
    NodeList nodeList = root.getChildNodes();
    // 遍历子节点,获取内部的每一个节点
    for (int i = 0; i < nodeList.getLength(); i++) {
     Node node = nodeList.item(i);
     ...
    }
    ...
  4. 常用api
//获取属性值
element.getAttribute();
//获取属性节点,没有则null
element.getAttributeNode();
//根据标签名返回当前节点下的后代(子子孙孙)节点
element.getElementsByTagName();
//获取标签名
element.getTagName();


//获取当前节点及其子节点的所有文本内容
node.getTextContent();
//获取儿子子节点 
node.getChildNodes();
//获取节点名字(属性节点返回属性名字,元素节点返回标签名,Text节点返回"#text",Document节点返回"#document")
node.getNodeName();
//获取节点值(属性节点返回属性值,文本节点返回文本内容,Comment节点返回内容,CDATASection节点返回内容,其他节点返回null);
node.getNodeValue();
//返回当前节点的第一个子节点 
node.getFirstChild();
//返回当前节点的最后子节点
node.getLastChild();
//获取节点类型
node.getNodeType();
//返回下一个兄弟节点
node.getNextSibling();
//返回上一个兄弟节点
node.getPreviousSibling();
//不包含命名空间的名字
node.getLocalName();
//以当前节点为根节点获取一个document对象
node.getOwnerDocument();

解析实战

下面是一段显示近三日天气的xml,分别采用三种方式进行解析。

<weatherinfo>
    <data d_id="01">
        <date>2016-05-07</date>
        <icon>d04|n04</icon>
        <weather>雷阵雨</weather>
        <temperature>36℃~28℃</temperature>
        <winddirect>西南风3-4级</winddirect>
    </data>
    <data d_id="02">
        <date>2016-05-08</date>
        <icon>d04|n04</icon>
        <weather>雷阵雨</weather>
        <temperature>32℃~26℃</temperature>
        <winddirect>西风3-4级转西北3-4级</winddirect>
    </data>
    <data d_id="03">
        <date>2016-05-09</date>
        <icon>d04|n04</icon>
        <weather>雷阵雨</weather>
        <temperature>32℃~26℃</temperature>
        <winddirect>西北风3-4级</winddirect>
    </data>
</weatherinfo>  

首先根据xml创建一个Weather类。实现如下:

public class Weather {
    private String id;
    private String date;
    private String icon;
    private String weather;
    private String temperature;
    private String winddirect;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String getTemperature() {
        return temperature;
    }

    public void setTemperature(String temperature) {
        this.temperature = temperature;
    }

    public String getWinddirect() {
        return winddirect;
    }

    public void setWinddirect(String winddirect) {
        this.winddirect = winddirect;
    }
}
  • PULL解析
public static List<Weather> pullParser(InputStream in) throws XmlPullParserException, IOException {
       //初始化核心类
        XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
        XmlPullParser parser=factory.newPullParser();
        parser.setInput(in,"utf-8");
        //初始化集合
        List<Weather> list=new ArrayList<>();
        Weather weather=null;
        boolean flag=false;//weather类实例化的标识
        //获取事件类型
        int type=parser.getEventType();
        while(type!=XmlPullParser.END_DOCUMENT){
            switch (type) {
                //开始标签
                case XmlPullParser.START_TAG:
                    //如果开始标签是data,初始化Weather类
                   if(parser.getName().equals("data")){
                         weather=new Weather();
                         //读取属性值
                         String id=parser.getAttributeValue(null,"d_id");
                         weather.setId(id);
                         flag=true;
                         list.add(weather);

                    }
                   if(flag){//如果Weather类已实例化,就开始设置值
                       if(parser.getName().equals("date")){
                          //读取当前START_TAG的下一个文本节点
                           weather.setDate(parser.nextText());
                       }
                       else if(parser.getName().equals("weather")){
                           weather.setWeather(parser.nextText());
                       }
                       else if(parser.getName().equals("icon")){
                           weather.setIcon(parser.nextText());
                       }
                       else if(parser.getName().equals("temperature")){
                           weather.setTemperature(parser.nextText());
                       }
                       else if(parser.getName().equals("winddirect")){
                           weather.setWinddirect(parser.nextText());
                       }
                   }

                    break;
                //闭合标签
                case XmlPullParser.END_TAG:
                    if(parser.getName().equals("data")){
                        flag=false;
                        weather=null;
                    }
                    break;
            }
            //开始下一次解析事件
            type=parser.next();
        }
        return list;
    }
  • SAX解析
 public static List<Weather> saxParser(InputStream in) throws ParserConfigurationException, SAXException, IOException{
        SAXParserFactory factory=SAXParserFactory.newInstance();
        SAXParser parser=factory.newSAXParser();
        XmlHandler handler=new XmlHandler();//继承自DefaultHandler
        parser.parse(in,handler);//插入一个自定义的xml处理器
        return handler.getList();
    }

    static class XmlHandler extends DefaultHandler{

        private List<Weather> list;
        private String tagName;
        private boolean flag=false;
        private Weather weather;

        /** * 开始读取文档 * @throws SAXException */
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            list=new ArrayList<>();
        }

        /** * 开始读取元素 */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            //uri:命名空间
            //localName:不带前缀(命名空间)的标签名
            //qName:带前缀的标签名
            //attributes:属性集合
            this.tagName=localName;
            if(tagName.equals("data")){
                weather=new Weather();
                String id=attributes.getValue(0);
                weather.setId(id);
                flag=true;
            }
            //
        }

        /** * 开始读取Text */
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);

            String str=new String(ch,start,length).trim();
            if(tagName!=null){
                if(flag){
                    if(tagName.equals("date")){
                        weather.setDate(str);
                    }else if(tagName.equals("icon")){
                        weather.setIcon(str);
                    }else if(tagName.equals("weather")){
                        weather.setWeather(str);
                    }else if(tagName.equals("temperature")){
                        weather.setTemperature(str);
                    }else if(tagName.equals("winddirect")){
                        weather.setWinddirect(str);
                    }
                }
            }

        }

        /** * 结束读取元素 */
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            if(localName.equals("data")){
                list.add(weather);
                flag=false;
            }
            tagName=null;
        }

        /** * 结束读取文档 */
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
        }


        public List<Weather> getList(){
            return list;
        }


    }
  • DOM解析
public static List<Weather> domParser(InputStream in) throws ParserConfigurationException, SAXException, IOException, XmlPullParserException {
        /** * 初始化核心API */
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        DocumentBuilder builder=factory.newDocumentBuilder();
        Document document=builder.parse(in);
        List<Weather> list=new ArrayList<>();
        NodeList nodes=document.getElementsByTagName("data");

        for(int i=0;i<nodes.getLength();i++ ){
            Element element= (Element) nodes.item(i);
            Weather weather=new Weather();
            weather.setId(element.getAttribute("d_id"));
            NodeList childs=element.getChildNodes();
            for(int j=0;j<childs.getLength();j++){
                Node temp=childs.item(j);
                if(temp.getFirstChild()!=null){
                    if(temp.getNodeName().equals("date")){
                        weather.setDate(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("icon")){
                        weather.setIcon(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("weather")){
                        weather.setWeather(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("temperature")){
                        weather.setTemperature(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("winddirect")){
                        weather.setWinddirect(temp.getFirstChild().getNodeValue());
                    }

                }}
            list.add(weather);

        }
        return list;
    }

END

你可能感兴趣的:(android,xml)