XML解析总结

本文整理自用,部分内容参考http://blog.youkuaiyun.com/anladeyatou/article/details/7446938

XML解析总结

解析方式:3种解析方式,分别是DOM解析,SAX解析,PULL解析。

————————–DOM解析———————

》DOM简介

    dom全称Document Object Model ,为xml文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个主流内存的树结构,然后代码就可以使用dom接口来操作这个树结构

》DOM的特点

     >优点

              1.整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能

              2.通过树形结构存取xml文档

              3.可以在树的某个节点上向前或向后移动

     >缺点

              1.将整个文档调入内存(包括无用的节点),浪费时间和空间

        >适用场合

              一旦解析了文档还需多次访问这些数据;硬件资源充足(内存,cpu)

》DOM解析步骤

  1.创建解析器工厂

  2.获得解析器工厂

  3.接受一个xml文档作为输入参数名,并得到一个xml的文档对象(Document)

  4.操作文档对象

》解析实例:

public class MainActivity extends Activity {

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

        ArrayList<Person> list = new ArrayList<Person>();

        //判断SDcard是否是挂载状态
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            //得到文件对象
            File file = Environment.getExternalStorageDirectory();
            //创建文档工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            try {
                //得到编辑器
                DocumentBuilder builder = factory.newDocumentBuilder();
                //通过编辑器 得到文件文档对象
                Document document = builder.parse(new File(file.getPath()+"/data.xml"));
                //得到文档的根元素
                Element element = document.getDocumentElement();
                //得到一个子节点集合
                NodeList childNodes = element.getChildNodes();
                for (int i = 0; i < childNodes.getLength(); i++) {
                    //创建一个person对象  用于存储解析出来的数据
                    Person p = new Person();
                    Node node = childNodes.item(i);
                    if (node.getNodeType()==node.ELEMENT_NODE) {
                        Element element2  = (Element) node;
                        String id = element2.getAttribute("id");
                        p.id=Integer.parseInt(id.trim());

                        NodeList childNodes2 = element2.getChildNodes();
                        for (int j = 0; j < childNodes2.getLength(); j++) {
                            Node node2 = childNodes2.item(j);
                            if (node2.getNodeType()==node2.ELEMENT_NODE) {
                                Element element3 = (Element) node2;
                                String value = element3.getFirstChild().getNodeValue();
                                if (element3.getNodeName().equals("name")) {
                                    p.name=value;
                                }else if (element3.getNodeName().equals("age")) {
                                    p.age=value;
                                }
                            }
                        }
                        list.add(p);
                    }
                }


            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        ListView lv = (ListView) findViewById(R.id.lv);
        lv.setAdapter(new ArrayAdapter<Person>(this, android.R.layout.simple_expandable_list_item_1, android.R.id.text1, list));


    }



}

————————–SAX解析———————————-

》Sax定义

     SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于android等移动设备

     SAX全称是Simple API for Xml,既是指一种接口,也是一个软件包

     作为接口,sax是事件驱动型xml解析的一个标准接口

》Sax特点

    1. 解析效率高,占用内存少

    2.可以随时停止解析

    3.不能载入整个文档到内存

    4.不能写入xml

    5.SAX解析xml文件采用的是事件驱动

—sax并不需要解析完 整个文档,在按内容顺序解析文档的过程中,sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件

》Sax工作原理

     Sax的工作原理简单的说,就是对文档进行顺序扫描,扫描到文档(document)开始与结束,扫描到元素(element)开始、结束等地方时调用事件处理

     处理函数做相应动作,然后继续扫描,直到文档结束。

》Sax解析文档过程

       1.继承DefaultHandler  ,并实现方法      

       2.创建SAX解析器工厂

       3.获得解析器

       4.获得输入流

       5.使用输入流,和实现接口作参数,调用解析器的解析方法进行解析

》defaultHandler 接口是实现contentHandler接口

     ContentHandler接口中的常用方法

             >startDocument()

                        当遇到文档开头的时候,调用这个方法,可以在其中做一些与准备工作

             >endDocument()

                         当文档结束的时候,调用这个方法,可以在其中做一些善后工作

             >startElement(String namespaceURL, String localName, String qName, Attributes atts)

                         当读到一个开始标签的时候,会触发这个方法。namespaceURL就是命名空间,localName是不带命名空间前缀的标签名,

                         qName是待命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。

             >endElement(String uri, String localName, String name)

                        当遇到结束标签的时候,调用这个方法

              >characters(char[] ch, int start, int length)

                        这个方法用来处理在xml文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,

                        使用new String(ch, start, length)就可以获取内容

》SAX解析实例

**一、第一步需要一个DefaultHandler的实例,并实现内部方法用于解析**
public class PersonHandler extends DefaultHandler {
    private Person p;//实体类
    private String ele_name;
    private List<Person> list;//实体类集合

    //【1】开始解析文档
    @Override
    public void startDocument() throws SAXException {
        //实例化集合
        list = new ArrayList<Person>();

        super.startDocument();
    }


    //【2】解析元素头标签 例如:<element>
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        ele_name = localName;
        if ("person".equals(ele_name)) {
            System.out.println("添加ID");
            p = new Person();
            p.setId(Integer.parseInt(attributes.getValue(0)));
        }

        super.startElement(uri, localName, qName, attributes);
    }

    //【3】解析元素中的文本 例如:<element>文本</element>
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //得到文本
        String text = new String(ch,start,length);
        if (p!=null) {
            if ("name".equals(ele_name)) {
                System.out.println("添加名字");
                p.setName(text);
            }else if ("age".equals(ele_name)) {
                System.out.println("添加年龄");
                p.setAge(Integer.parseInt(text));
            }
        }
        super.characters(ch, start, length);
    }
    public List<Person> getList(){
        return list;
    }
    //【4】解析元素结束标签 例如:</element>
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        ele_name=localName;
        if ("person".equals(ele_name)) {
            System.out.println("添加对象");
            //整个元素解析完毕,对象初始化完毕,添加进入集合
            list.add(p);
            //初始化实体类对象,准备进入下次解析数据
            p=null;
        }
        ele_name="";
        super.endElement(uri, localName, qName);
    }
}
第二步:开始sax解析
public class MainActivity extends Activity {
    List<Person> list;
    private PersonHandler ph;

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

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File file = Environment.getExternalStorageDirectory();
        //创建工厂对象(工厂模式)
            SAXParserFactory factory = SAXParserFactory.newInstance();
            try {
                //通过工厂实例化一个sax解析对象
                SAXParser saxParser = factory.newSAXParser();
                //获得事件源
                XMLReader reader = saxParser.getXMLReader();
                //构建事件处理器的实例
                ph=new PersonHandler();
                reader.setContentHandler(ph);
                //解析,数据已存在事件处理器的实例中的list集合里
                reader.parse(new InputSource(new FileInputStream(file.getPath()+"/data.xml")) );
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

——————————pull解析—————————–

》pull解析器简介

    1.pull解析器是android内置的解析器,解析原理与sax类似

    2.pull它提供了类似的事件。
          如:开始元素和结束元素事件,使用parse.next()可以进入下一个元素并触发相应的事件,事件将作为数值代码被发送
          因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法获取下一个Text类型节点的值

》pull与sax的不同之处

      1.pull读取xml文件后触发相应的事件调用方法返回的是数字。

      2.pull可以在程序中控制,想解析到哪里就可以停止到哪里

      3.Android中更推荐使用pull解析

》pull解析步骤

  1.创建解析器对象

      XmlPullParser paser = Xml.newPullParser();

  2.进行解析

         paser.setInput(input,"utf-8");

  3.产生第一个解析事件

          int eventType = paser.getEventType();

   4.可以使用循环判断是否继续解析

            while(eventType!=XmlPullParser.END_DOCUMENT){}

》解析实例

public class MainActivity extends Activity {
    String strUrl="http://www.sciencenet.cn/xml/iphoneInterface.aspx?type=news&nums=20&pass=";
    List<New> list = null;//实体类集合
    private InputStream is=null;//输入流
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //开启异步任务或者子线程获得网络数据,得到输入流--is;
        //******


    }
    //解析方法
    public List<New> pullParseXml(InputStream is){
        New n=null;//实体类对象
        try {
            //创建工厂对象
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

            XmlPullParser pullParser =factory.newPullParser();
                        pullParser.setInput(is, "utf-8");//传入输入流并设置字符集

            int eventType = pullParser.getEventType();//得到元素类型
            while (eventType!=XmlPullParser.END_DOCUMENT) {

                switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    list=new ArrayList<New>();
                    break;
                case XmlPullParser.START_TAG:
                    String name = pullParser.getName();
                    if ("title".equals(name)) {
                        n = new New();
                        n.setTitle(pullParser.nextText());
                    }
                    if ("link".equals(name)) {
                        n.setLink(pullParser.nextText());
                    }
                    if ("imgs".equals(name)) {
                        n.setImgs(pullParser.nextText());
                    }
                    if ("description".equals(name)) {
                        n.setDescription(pullParser.nextText());
                    }
                    if ("copyright".equals(name)) {
                        n.setCopyright(pullParser.nextText());
                    }
                    if ("pubDate".equals(name)) {
                        n.setPubDate(pullParser.nextText());
                    }
                    if ("comments".equals(name)) {
                        n.setComments(pullParser.nextText());
                    }
                    break;
                case XmlPullParser.END_TAG:
                    //解析完添加到集合中
                    list.add(n);
                    n=null;
                    break;

                }
                eventType = pullParser.next();  
            }
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return list;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值