XML文档解析

XML文档的解析方式(4种):

1.SAX解析XML文件
2.DOM解析XML文件
3.JDOM解析XML文件
4.DOM4J解析XML文件

注意:XML文件的解析格式有两种:SAX解析和DOM解析(DOM , JDOM , DOM4J )

各种解析方法比较:

1.JDOM与DOM4J在性能测试时表示不佳,在测试10M的文档时内存溢出.
2.SAX表现较好,这主要依赖于与它特定的解析方式.一个SAX检测即将到来的XML流,但并没有载入内存 (当然在XML流被读入时,会有部分文档暂时隐藏于内存中)
3.DOM4J是这场测试中的获胜者,目前许多开源的项目中大量使用DOM4J,例如(Hibernate框架也使用DOM4J来读取XML配置文件.

一 , SAX解析XML文件
	步骤:
        1.创建一个SAX解析器工厂对象
        2.通过工厂对象创建一个SAX解析器对象
        3.创建一个数据处理器(需要自己编写)
        4.开始解析XML文件
    特点:
        1.基于事件驱动
            即在解析XML文件的中每一个标签时,都会回调数据处理器中所重写的方法.
        2.顺序读取,速度快
            从上到下依次读取
        3.不可以任意读取节点 ,灵活性差
        4.解析是占用的内存小.
        5.SAX更适用于对性能要求较高的设备上使用(例:Andriod开发)
public void saxParseXML() throws ParserConfigurationException, SAXException, IOException {
        //1.创建一个SAX解析器工厂对象
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        //2.通过工厂对象创建一个SAX解析器对象
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //3.创建一个数据处理器对象(数据处理器需要自己编写)
        PersonHandler personHandler = new PersonHandler();
        //4.开始解析XML文件
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/xml/person.xml");
        saxParser.parse(resourceAsStream, personHandler);

        List<Person> persons = personHandler.getPersons();
        for (Person person : persons) {
            System.out.println(person);
        }

数据处理器 PersonHandler类

package com.xml;

import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.org.apache.bcel.internal.generic.VariableLengthInstruction;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.naming.Name;
import java.util.ArrayList;
import java.util.List;

/**
* @Author: 薛云冲
* Created on 2019/4/25 22:45
*/
public class PersonHandler extends DefaultHandler {
   private List<Person> persons  = new ArrayList<>();
   private Person p;//当前正在解析的person.
   private String tag;//用于记录当前正在解析的标签名.

   public List<Person> getPersons(){
       return persons;
   }
   /*
       在开始解析XML文档时调用
    */
   @Override
   public void startDocument() throws SAXException {
       super.startDocument();
       System.out.println("开始解析文档...");
   }

   /*
       在XML文档解析结束时调用
    */
   @Override
   public void endDocument() throws SAXException {
       super.endDocument();
       System.out.println("解析文档结束...");
   }

   /**
    * @param uri 命名空间
    * @param localName 不带前缀的标签名
    * @param qName 带前缀的标签名
    * @param attributes 当前标签的属性集合
    * @throws SAXException
    */
   /*
       解析开始元素时调用
    */
   @Override
   public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
       super.startElement(uri, localName, qName, attributes);
       if("person".equals(qName)){
           p = new Person();
           String value = attributes.getValue("personid");
           p.setPersonid(value);
       }
       tag = qName;
   }

   /*
       解析结束元素时调用
    */
   @Override
   public void endElement(String uri, String localName, String qName) throws SAXException {
       super.endElement(uri, localName, qName);
       if ("person".equals(qName)) {
           persons.add(p);
       }
       tag = null ;
   }

   /*
       解析内容时调用.
    */
   @Override
   public void characters(char[] ch, int start, int length) throws SAXException {
       super.characters(ch, start, length);
       if(tag!=null){
           if ("name".equals(tag)) {
               p.setName(new String(ch, start, length));
           }else if("address".equals(tag)){
               p.setAddress(new String(ch,start,length));
           }else if("tel".equals(tag)){
               p.setTel(new String(ch,start,length));
           }else if("fax".equals(tag)){
               p.setFax(new String(ch,start,length));
           }else if("email".equals(tag)){
               p.setEmail(new String(ch,start,length));
           }
       }
   }
}


person.xml文件的内容


<people>
   <person personid="E01">
       <name>Tony Blairname>
       <address>10 Downing Street,London,UKaddress>
       <tel>(061) 98765tel>
       <fax>(061) 98765fax>
       <email>[email protected]email>
   person>
   <person personid="E02">
       <name>Bill Clintonname>
       <address>White House,USAaddress>
       <tel>(001) 6400 98765tel>
       <fax>(001) 6400 98765fax>
       <email>[email protected]email>
   person>
people>
二 , DOM解析XML文件
   步骤:
       1.创建一个DOM解析器(文档生成器)工厂对象
       2.通过工厂对象创建一个DOM解析器对象
       3.解析文档
       4.从内存中读取数据生成对象
   特点:
       1.基于树型结构,
       2.通过解析器一次性把文档加载到内存中,所以会比较占用内存,
       3.可以随机访问,更加灵活,适合web端开发.
 @Test
    public void domParseXML() throws IOException, SAXException, ParserConfigurationException {
//        1.创建一个DOM解析器(文档生成器)工厂对象
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//        2.通过工厂对象创建一个DOM解析器对象
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//        3.解析文档
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com\\xml\\person.xml");
        //此代码完成后,整个XML文档已经被加载到内存中,以树状形式存储;
        Document parse = documentBuilder.parse(resourceAsStream);
//        4.从内存中读取数据生成对象

        //获取节点名称为person的所有节点,返回节点集合.
        NodeList personNodeList = parse.getElementsByTagName("person");
        ArrayList<Person> persons = new ArrayList<>();
        Person person = null;
        //次循环会迭代两次
        for (int i = 0; i < personNodeList.getLength(); i++) {
            Node personNode = personNodeList.item(i);
            person = new Person();
            //获取节点属性值;
            String personid = personNode.getAttributes().getNamedItem("personid").getNodeValue();
            person.setPersonid(personid);
            //获取当前节点的所有子节点
            NodeList childNodes = personNode.getChildNodes();
            for (int j = 0; j <childNodes.getLength() ; j++) {
                Node item = childNodes.item(j);
                String nodeName = item.getNodeName();
                if("name".equals(nodeName)){
                    person.setName(item.getFirstChild().getNodeValue());
                }else if("address".equals(nodeName)){
                    person.setTel(item.getFirstChild().getNodeValue());
                }
                else if("tel".equals(nodeName)){
                    person.setTel(item.getFirstChild().getNodeValue());
                }
                else if("fax".equals(nodeName)){
                    person.setFax(item.getFirstChild().getNodeValue());
                }
                else if("email".equals(nodeName)){
                    person.setEmail(item.getFirstChild().getNodeValue());
                }
            }
            persons.add(person);
        }
        System.out.println("结果:");
        for (Person person1 : persons) {
            System.out.println(person1);
        }
    }
三 , JDOM解析XML文件
      步骤:
          1.创建JDOM解析器
          2.解析文档
          3.从内存中读取数据生成对象
      特点:
          1.基于树型结构
          2.第三方组件
          3.与DOM的区别:
              (1).第三方开源组件.
              (2).实现使用JAVA的Collection接口.
              (3).效率比DOM更加快,更容易让使用者接受.
  @Test
    public void jdomParseXML() throws JDOMException, IOException {
        //1.创建JDOM解析器
        SAXBuilder builder = new SAXBuilder();
        //2.解析文档
        //将资源转化为流
        InputStream resourceAsStream = Thread.currentThread()
                .getContextClassLoader().getResourceAsStream("com\\xml\\person.xml");
        //解析资源流
        org.jdom2.Document build = builder.build(resourceAsStream);
        //3.从内存中读取数据生成对象
        //得到根元素
        Element rootElement = build.getRootElement();

        List<Person> persons = new ArrayList<>();
        Person person =null;

        List<Element> children = rootElement.getChildren();
        for (Element child : children) {
            person =new Person();
            String attributeValue = child.getAttributeValue("personid");
            person.setPersonid(attributeValue);
            List<Element> children1 = child.getChildren();
            for (Element element : children1) {
                String name = element.getName();
                if("name".equals(name)){
                    person.setName(element.getText());
                }else if("address".equals(name)){
                    person.setAddress(element.getText());
                }else if("tel".equals(name)){
                    person.setTel(element.getText());
                }else if("fax".equals(name)){
                    person.setFax(element.getText());
                }else if("email".equals(name)){
                    person.setEmail(element.getText());
                }
            }
            persons.add(person);
        }
        for (Person p : persons) {
            System.out.println(p);
        }
    }
四 , DOM4J解析XML文件
	  步骤:
           1.创建DOM4J解析器
           2.解析文档
           3.从内存中读取数据生成对象
       特点:
           1.基于树型结构
           2.第三方组件
           3.解析速度快,效率更高,使用JAVA中的迭代器进行数据读取,在web框架中使用较多,比如(Hibernate框架) 
 @Test
    public void dom4jParseXML() throws DocumentException {
        //1.创建DOM4J解析器对象
        SAXReader reader = new SAXReader();
        //2.解析文件
        //将xml文件转化为流
        InputStream resourceAsStream = Thread.currentThread()
                .getContextClassLoader().getResourceAsStream("com\\xml\\person.xml");
        //解析资源流
        org.dom4j.Document read = reader.read(resourceAsStream);
        //3.从内存中读取数据生成对象
        //获取根元素
        org.dom4j.Element rootElement = read.getRootElement();
        List<Person> persons = new ArrayList<>();
        Person person = null;
        //获取子节点
        Iterator<org.dom4j.Element> iterator = rootElement.elementIterator();
        while (iterator.hasNext()){
            person = new Person();
            org.dom4j.Element next = iterator.next();
            person.setPersonid(next.attributeValue("personid"));
            //获取子节点
            Iterator<org.dom4j.Element> iterator1 = next.elementIterator();
            while (iterator1.hasNext()){
                org.dom4j.Element next1 = iterator1.next();
                String name = next1.getName();
                if("name".equals(name)){
                    person.setName(next1.getText());
                }else if("address".equals(name)){
                    person.setAddress(next1.getText());
                }else if("tel".equals(name)){
                    person.setTel(next1.getText());
                }else if("fax".equals(name)){
                    person.setFax(next1.getText());
                }else if("email".equals(name)){
                    person.setEmail(next1.getText());
                }
            }
            persons.add(person);
        }
        for (Person person1 : persons) {
            System.out.println(person1);
        }
    }
五 , 把对象转换为XML文件格式,并写入指定文件.
 public void xmlEnCoder() throws FileNotFoundException {
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("test.xml"));
        XMLEncoder xmlEncoder = new XMLEncoder(bufferedOutputStream);
        Person p =new Person();
        p.setPersonid("1001");
        p.setName("盖伦");
        p.setAddress("德玛西亚");
        p.setFax("6000101011");
        p.setTel("6000101011");
        p.setEmail("[email protected]");
        
        xmlEncoder.writeObject(p);
        xmlEncoder.close();
        System.out.println("写入完成...");
    }
六 , 从XML文件中读取对象
  /*
        从xml文件中读取对象
     */
    @Test
    public void xmlDeCoder() throws FileNotFoundException {
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("person.xml"));
        XMLDecoder xmlDecoder = new XMLDecoder(bufferedInputStream);
        Person person = (Person)xmlDecoder.readObject();
        xmlDecoder.close();
        System.out.println("读取成功...");
        System.out.println(person);
    }

你可能感兴趣的:(XML文档解析)