android xml解析

xml 解析有三种,分别是SAX,PULL,DOM

用到的xml如下:

<apps>
    <app>
        <id>1id>
        <name>Google mapsname>
        <version>1.0version>
    app>
    <app>
        <id>2id>
        <name>chromename>
        <version>2.1version>
    app>
    <app>
        <id>3id>
        <name>google playname>
        <version>3.1version>
    app>

 apps>

SAX

SAX(Simple API For XML)是以流式的处理方式解析的,不记录所读的内容信息,是一种以事件驱动的XML API。主要对文档进行顺序扫描,当扫描到文档的开始和结束,元素的开始和结束时通知事件处理函数,由事件处理函数做相对应的操作,然后继续扫描,直到文档的结束。解析度快,占用内存少,非常适用使在Andoid移动设备中使用

使用步骤:
1. 新建 ContentHanlder 类继承 DefaultHandler 类,并重写父类的五个方法

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

2.创建函数 parseXMLWithSAX
3.调用函数 parseXMLWithSAX 解析 XML

我把使用到的xml文件放到assets文件夹下


import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Created by RainBowAndStar on 2018/4/3.
 */

public class ContentHandler extends DefaultHandler {
    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;
    private String TAG = "SAX";

    //开始解析 XML 文档,一般做初始化操作
    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
        version = new StringBuilder();
    }
    //开始解析结点
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //localName 记录当前结点的名字
        nodeName = localName;
    }
    //开始提取结点中内容
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        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 {
        if("app".equals(localName)){
            //可能包含回车或换行符
            Log.d(TAG, "endElement: "+nodeName);
            Log.d(TAG, "endElement: id = " + id.toString().trim());
            Log.d(TAG, "endElement: name = "+ name.toString().trim());
            Log.d(TAG, "endElement: version = "+ version.toString().trim());
            //打印结束后清空,否则会影响下一次内容的读取
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }
    //结束XML文档解析
    @Override
    public void endDocument() throws SAXException {
        Log.e(TAG, "endDocument: 文档结束" );
    }
}
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import javax.xml.parsers.SAXParserFactory;
import linxin.www.test.sax.ContentHandler;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getData();
    }


    private void getData() {
        StringBuffer sb = new StringBuffer();
        try {
            InputStream inputStream= getAssets().open("TestXML");
            byte[] bytes = new byte[1024];
            if(inputStream.read(bytes)!= 0 ){
                sb.append(new String (bytes,0,bytes.length));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        paraseXMLWithSAX(sb.toString().trim());
    }



    //TODO 用SAX方式解析XML
    private void paraseXMLWithSAX(String xmlData){
        Log.d("SAX", "paraseXMLWithSAX: "+xmlData);
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            XMLReader reader = factory.newSAXParser().getXMLReader();
            ContentHandler handler = new ContentHandler();
            //将contentHandler的实例设置到XMLReader中
            reader.setContentHandler(handler);
            //开始解析
            InputSource is = new InputSource(new StringReader(xmlData));
            is.setEncoding("ISO-8859-15");
            reader.parse(is);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

Pull

PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。
**解析过程:**XML pull提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时,自动生成EndDocument事件。

读取到xml的声明返回 START_DOCUMENT;
读取到xml的开始标签返回 START_TAG
读取到xml的文本返回 T XT

取到xml的结束标签返回 END_TAG
读取到xml的结束返回 END_ DOCUMENT

package linxin.www.test;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getData();

    }





    private void getData() {
        StringBuffer sb = new StringBuffer();
        try {
            InputStream inputStream= getAssets().open("TestXML");
            byte[] bytes = new byte[1024];
            if(inputStream.read(bytes)!= 0 ){
                sb.append(new String (bytes,0,bytes.length));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        parseXMLWithPull(sb.toString().trim());
    }




    //TODO  用Pull方式解析XML
    private void parseXMLWithPull(String xmlData){
        String TAG ="PULL";
        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){
                    //开始解析XML
                    case XmlPullParser.START_TAG:{
                        //nextText()用于获取结点内的具体内容
                        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(TAG, "parseXMLWithPull: id is "+ id);
                            Log.d(TAG, "parseXMLWithPull: name is "+ name);
                            Log.d(TAG, "parseXMLWithPull: version is "+ version);
                        }
                    } break;
                    default: break;
                }
                //下一个
                eventType = xmlPllParser.next();
            }
        } catch (Excetion e) {
            e.printStackTrace();
        }
    }
}

DOM

DOM,即对象文档模型,它是将整个XML文档载入内存(所以效率较低,不推荐使用),每一个节点当做一个对象,结合代码分析。DOM实现时首先为XML文档的解析定义一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,这样代码就可以使用DOM接口来操作整个树结构。 由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。 当然,如果XML文件的内容比较小,采用DOM是可行的。
工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档。
使用步骤:
采用DOM解析时具体处理步骤是:

首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例
然后利用DocumentBuilderFactory创建DocumentBuilder
然后加载XML文档(Document)
然后获取文档的根结点(Element)

然后获取根结列表(NodeList),
然后使用再获取子节点列表中的需要读取的结点。,


/**
 * Created by RainBowAndStar on 2018/4/4.
 */

public class App {

    private String id =  null ;
    private String name = null;
    private  String version = null;

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVersion() {
        return version;
    }



public void setVersion(String version) { 

        this.version = version;
    }
}

import android.content.Context;
import android.util.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

/**
 * Created by RainBowAndStar on 2018/4/4.
 */

public class DomHelper {

    public static ArrayList queryXML(Context context)
    {
        ArrayList apps = new ArrayList();
        try {
            //①获得DOM解析器的工厂示例:
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            //②从Dom工厂中获得dom解析器
            DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
            //③把要解析的xml文件读入Dom解析器
            Document doc = dbBuilder.parse(context.getAssets().open("TestXML"));
            System.out.println("处理该文档的DomImplemention对象=" + doc.getImplementation());
            //④得到文档中名称为apps的元素的结点列表
            NodeList nList = doc.getElementsByTagName("app");      //TODO 这里不用一层层获取,不用获取到apps然后再获取app
            //⑤遍历该集合,显示集合中的元素以及子元素的名字
            for(int i = 0;i < nList.getLength();i++)
            {
                //先从元素开始解析
                Element personElement = (Element) nList.item(i);
                App app = new App();
           //     app.setId(Integer.valueOf(personElement.getAttribute("id")));

                //获取person下的name和age的Note集合
                NodeList childNoList = personElement.getChildNodes();        //3
                for(int j = 0;j < childNoList.getLength();j++)
                {
                    Node childNode = childNoList.item(j);
                    //判断子note类型是否为元素Note
                    if(childNode.getNodeType() == Node.ELEMENT_NODE)
                    {
                        Element childElement = (Element) childNode;
                        if("id".equals(childElement.getNodeName()))
                            app.setId(childElement.getFirstChild().getNodeValue());
                        else if("name".equals(childElement.getNodeName()))
                            app.setName(childElement.getFirstChild().getNodeValue());
                        else if("version".equals(childElement.getNodeName())){
                            app.setVersion(childElement.getFirstChild().getNodeValue());
                        }
                    }
                }
                apps.add(app);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        for(int k = 0 ;k
            Log.d("Dom",apps.get(k).getId() 
                                                                                                                                                                                            );

                                                                                                                                                                                                    Log.d("Dom",apps.get(k).getName());
            Log.d("Dom",apps.get(k).getVersion());


}
  return apps;
    }
}

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DomHelper.queryXML(this);
}

}
参考文章: https://www.cnblogs.com/guolingyun/p/6148462.html

你可能感兴趣的:(Android筑基)