XML四种解析(慕课笔记)

1.初次邂逅XML

表现:以“.xml”为文件扩展名的文件
储存:树状结构
version="1.0" encoding="utf-8">
 
    id="1">
        <name>冰与火之歌name>
        乔治马丁
        <year>2014year>
        89
    
    id="2">
        <name>安徒生name>
        乔治马丁
        <year>2014year>
        89
        English
    
为什么要使用XML
思考1.不同应用程序之间的通信?
思考2.不同系统间的通信的通信?
思考3.不同平台间的通信的通信?

2.在java程序中如何获取xml文件的内容

解析方式:DOM SAX DOM4J JDOM

常见节点类型
节点类型 NodeType Named Constant nodeName的返回值 nodeValue的返回值
Element 1 ELEMENT_NODE element name null
Attr 2 ATTRIBUTE_NODE 属性名称 属性值
Text 3 TEXT_NODE text 节点内容
DOM方式 (将xml全部加载解析,再执行)
public void nodePrase() throws Exception{
        //1.创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
        //2.创建一个DocumentBuider的对象
        DocumentBuilder db=dbf.newDocumentBuilder();
        //3.DocumentBuilder .parse()解析xml文件 得到document对象
        Document document=db.parse("books.xml");
        //4.获取所有book节点
        NodeList bookList = document.getElementsByTagName("book");
        //5.遍历每一个book节点
        for(int i=0;i//6.通过item(i)获取每一本book节点 ,nodelist的索引从0开始
          Node book = bookList.item(i);
         //7.获取book的所有属性
         NamedNodeMap attrs = book.getAttributes();
           //8.遍历book属性
          for(int j=0;j//9.获取属性名
            String nodeName = attrs.item(j).getNodeName();
            System.out.println(nodeName);
            //10.获取属性值
            String nodeValue = attrs.item(j).getNodeValue();
            System.out.println(nodeValue);
          }

           //方式 二   
            //前题已经知道book节点有其只要一个id属性
           //Element book = (Element) bookList.item(i);  //强转成Element 可以调用 attributeValue("id") 直接拿到属性值
          // String attrValue=book.attributeValue("id");

           //解析book节点的子节点
             NodeList childNodes=book.getChildNodes();
            //遍历childNodes获取每个节点的 节点名和节点值  (空白和换行也会当成子节点)
             for(int k=0;k//区分出text类型的Node以及element类型的node
               if(childNodes.item(k).getNodeType()==Node.ELEMENT_NODE){
                 //获取element类型的节点名
                   String nodeName=childNodes.item(k).getNodeName();
                   System.out.println(nodeName);
                    //childNodes.item(k).getNodeValue();//为空 
                    //String nodeValue = childNodes.item(k).getFirstChild().getNodeValue(); //节点里面的内容也被当成一个节点
                 String nodeValue = childNodes.item(k).getTextContent();//获取节点里面的所有文本值 (当该节点下子节点唯一时可以用,文本值唯一)
                    System.out.println(nodeValue);
               } 
             }
        }
    }
SAX解析 (边加载边解析)

1.通过SAXParserFactory的静态newInstance()方法获取SAXParserFactord的实例factory

2.通过SAXParserFactory实例获取SAXParser实例

3.创建SAXPraserHandler对象(需要重写 startDocument() endDocument() startElement() endElement()方法 )

4.解析xml文件

//如何保存book的节点信息呢

通过book的javabean对象来保存

    //1.通过SAXParserFactory的静态newInstance()方法获取SAXParserFactord的实例factory
        SAXParserFactory sf = SAXParserFactory.newInstance();
        //2.通过SAXParserFactory实例获取SAXParser实例
        SAXParser paser = sf.newSAXParser();
        //3.创建SAXPraserHandler对象
        SAXParserHandler ph = new SAXParserHandler();
        //4.解析xml文件
        paser.parse("books.xml", ph);
        //5.获取ph中封装好的javabean对象
        List list = ph.getList();
        for (Object object : list) {
            System.out.println(object);
        }

//SAXParserHandler类 (核心 )
package com.heima.xml文件的解析;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXParserHandler extends DefaultHandler{
    private int bookIndex;
    private String value;
    private Book book;
    List list=new ArrayList();
    /**
     * 用来遍历xml的开始标签
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        //调用DefaultHandler
        super.startElement(uri, localName, qName, attributes);
        //开始解析book元素标签
        if(qName.equals("book")){
            //创建book对象
            book=new Book();
            this.bookIndex++;
            System.out.println("===============开始遍历第"+bookIndex+"本书===============");
            //已知Book属性的名称,根据属性名称获取属性值
            /*String value = attributes.getValue("id");
            System.out.println("book的节点"+value);*/

            //不知道book元素下的属性的个数
            int numm=attributes.getLength();
            for(int i=0;i"book的"+i+1+"节点的节点名:"+attributes.getQName(i));
                System.out.println("book的"+i+1+"节点的节点值"+attributes.getValue(i));    

                if(attributes.getQName(i).endsWith("id")){
                    book.setId(attributes.getValue(i)+"");
                }
            }
        }else if(!qName.equals("book")||!qName.equals("bookstore")){
            System.out.print("节点名是:"+qName);
        }

    }

    /**
     * 用来遍历xml的结束标签
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {

        super.endElement(uri, localName, qName);
        if(qName.equals("book")){
            list.add(book);
            book=null;
            System.out.println("=============结束遍历第"+bookIndex+"本书=============");
        }
        else if(qName.endsWith("name")){
            book.setName(value);
        }
        else if(qName.endsWith("author")){
            book.setAuthor(value);
        }
        else if(qName.endsWith("year")){
            book.setYear(value);
        }
        else if(qName.endsWith("price")){
            book.setPrice(value);
        }
        else if(qName.endsWith("language")){
            book.setLanguage(value);
        }
    }
    /**
     * 用来标识解析开始
     */
    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.startDocument();
        System.out.println("sax解析开始");
    }
    /**
     * 用来标识解析结束
     */
    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.endDocument();
        System.out.println("sax解析结束");
    }
    @Override
    /**
     * 获取属性文本的文本信息
     */
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        // TODO Auto-generated method stub
        super.characters(ch, start, length);
        value = new String(ch, start, length);
        if(!"".equals(value.trim())){
            System.out.println("   节点值:"+value);
        }
    }

    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
}
 
  
JDOM解析

0.导入jar包

//对 books.xml文件进行JDOM解析

1.创建一个SAXBuilder的对象

2.创建一个输入流,将xml文件加载到输入流中

3.通过document对象获取xml文件的根节点

4.获取根节点下的子节点的List集合

    private Book bk;//book的实体
    private List list=new ArrayList();//存放解析后 生成的book实体
    @Test
    public void  JDOMPrase() throws Exception{
        //导入jar包
        //对 books.xml文件进行JDOM解析
        //1.创建一个SAXBuilder的对象
        SAXBuilder saxBuilder=new SAXBuilder();
        //2.创建一个输入流,将xml文件加载到输入流中
        InputStream in=new FileInputStream("src/res/books.xml");
        //解决乱码(用可以指定字符集的流进行包装)
        InputStreamReader isr = new InputStreamReader(in, "utf-8");
        Document document = saxBuilder.build(isr);
        //3.通过document对象获取xml文件的根节点
        Element rootElement = document.getRootElement();
        //4.获取根节点下的子节点的List集合
        List booklist = rootElement.getChildren();

        //继续进行解析
        for (Element book : booklist) {

            System.out.println("-------------开始解析第"+(booklist.indexOf(book)+1)+"书-----------");
            //解析book的属性
            List attributes = book.getAttributes();
            //知道属性名
            //String attributeValue = book.getAttributeValue("id");
            //System.out.println("");
            //针对不清楚book节点下属性的名字及数量
            for (Attribute attr : attributes) {
                //创建book实体
                bk =new Book();
                //获取到属性名和属性值(都是有实际值的节点)
                String name = attr.getName();
                String value = attr.getValue();
                System.out.println("属性名:"+name+"~"+"属性值:"+value);  
                //添加id
                if("id".equals(name)){
                    bk.setId(value);
                }
            }
            //对book节点的 子节点的节点名以及节点值的遍历
            List bookChilds = book.getChildren();
            for (Element element : bookChilds) {
                String name = element.getName();
                String value = element.getValue();
                System.out.println("节点名:"+name+"~"+"节点值:"+value);  
                //给book添加属性
                if(name.endsWith("name")){
                    bk.setName(value);
                }
                else if(name.endsWith("author")){
                    bk.setAuthor(value);
                }
                else if(name.endsWith("year")){
                    bk.setYear(value);
                }
                else if(name.endsWith("price")){
                    bk.setPrice(value);
                }
                else if(name.endsWith("language")){
                    bk.setLanguage(value);
                }
            }
            list.add(bk);
            bk=null;
            System.out.println(list);
            System.out.println("-------------结束解析第"+(booklist.indexOf(book)+1)+"书-----------");
        }
    }
DOM4j

​ 0.导入jar包

​ 1.创建SAXReader的对象reader

​ 2.通过reader对象的read方法加载books.xml文件,获取document对象

​ 3.通过document对象获取根节点

​ 4.通过element对象的elementIterator方法获取迭代器

​ 5.遍历迭代器,获取根节点中的信息

​ 6.获取book的属性值及属性名

​ 如果清楚xml文件的结构,也可以用xpath方法快速获取某个具体节点的属性。

private Book bk;//book的实体
    private List list=new ArrayList();//存放解析后 生成的book实体

    @Test
    public void DOM4jPrase() throws DocumentException{
        //创建SAXReader的对象reader
        SAXReader reader=new SAXReader();
        //通过reader对象的read方法加载books.xml文件,获取document对象
        org.dom4j.Document document = reader.read(new File("src/res/books.xml"));

        //通过document对象获取根节点
        org.dom4j.Element bookStore = document.getRootElement();
        //通过element对象的elementIterator方法获取迭代器
        Iterator elementIterator = bookStore.elementIterator();
        //遍历迭代器,获取根节点中的信息
        while(elementIterator.hasNext()){
            bk=new Book();
            System.out.println("====开始遍历某本书====");

            org.dom4j.Element book=(org.dom4j.Element) elementIterator.next();
            //获取book的属性值及属性名
            List attributes = book.attributes();
            for (org.dom4j.Attribute attr : attributes) {
                String name = attr.getName();
                String value = attr.getValue();
                System.out.println("节点名:"+name+"~"+"节点值:"+value);
                if("id".equals(name)){
                    bk.setId(value);
                }
            }
            Iterator eit = book.elementIterator();
            //遍历每一本书的节点
            while(eit.hasNext()){
                org.dom4j.Element bookChild = (org.dom4j.Element) eit.next();
                String name = bookChild.getName();
                String value = bookChild.getStringValue();
                System.out.println("节点名:"+name+"~"+"节点值:"+value);
                if(name.endsWith("name")){
                    bk.setName(value);
                }
                else if(name.endsWith("author")){
                    bk.setAuthor(value);
                }
                else if(name.endsWith("year")){
                    bk.setYear(value);
                }
                else if(name.endsWith("price")){
                    bk.setPrice(value);
                }
                else if(name.endsWith("language")){
                    bk.setLanguage(value);
                }
            }
            list.add(bk);
            bk=null;
            System.out.println(list);
            System.out.println("===结束遍历某本书====");
        }

    }

3.4种解析方式的比较

基础方法:DOM、SAX (DOM解析于平台无关的解析)(SAX基于事件驱动)

扩展方法:JDOM,DOM4J

DOM解析 是将xml文件 一次性加载到内存中

SAX解析 事件驱动 startDocument() endDocument() startElement() endElement()

DOM

优点 :

*形成了树结构,直观好理解,代码更易于修改

*解析过程中树结构保存在内存中,方便修改

缺点:

*当xml文件很大时,内存消耗比较大容易影响解析性能并可能造成内存溢出

SAX

优点:

*采用事件驱动模式,堆内存耗费比较小

*适用于只需要处理xml中数据时

缺点:

*不易于编码

*很难同时访问同一个xml中的多处数据

JDOM

*仅仅使用具体类而不使用接口

*API大量使用了CollectionS类

*开放源码

DOM4J

*JDOM的一种智能分支,它合并了许多超出基本xml,文档表示的功能

*DOM4J使用接口和抽象基本类方法,是一个优秀的Java XML API

*具有性能优异,灵活性好,功能强大和易于使用的特点

*开放源码

四种解析速度分析

@Test
    public void 性能测试() throws Exception{
        long s1 = System.currentTimeMillis();
        nodePrase();
        long s12 = System.currentTimeMillis();

        long s2 = System.currentTimeMillis();
        SAXParse();
        long s22 = System.currentTimeMillis();

        long s3 = System.currentTimeMillis();
        JDOMPrase();
        long s32 = System.currentTimeMillis();

        long s4 = System.currentTimeMillis();
        DOM4jPrase();
        long s42 = System.currentTimeMillis();

        System.out.println("DOM"+(s12-s1));
        System.out.println("SAX"+(s22-s2));
        System.out.println("JDOM"+(s32-s3));
        System.out.println("DOM4J"+(s42-s4));

    }

你可能感兴趣的:(java基础)