Java解析XML的方法小结

      在项目开发中,经常会涉及到许许多多和数据处理有关的环节,如数据采集、数据解析、数据存储、数据格式化等等,本文与大家分享交流java关于数据解析的相关知识。大家知道,实际项目中,在交互时使用较多的数据格式有json、xml(可扩展标记语言)。对于json格式数据的解析,已在《Java常用数据结构基础知识总结(二)》中与大家做了基本的介绍,有兴趣的朋友可以查阅。本文主要和大家一起学习解析XML格式数据的几种常用方法。

一、前期文档准备  

    首先我们准备好需要解析的XML文档,并针对该文档生成相应的Java实体类:
xml文档:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book id="1">
        <name>西游记</name>
        <author>吴承恩</author>
        <dynasty>明代</dynasty>
    </book>
    <book id="2">
        <name>红楼梦</name>
        <author>曹雪芹</author>
        <dynasty>清代</dynasty>
    </book>
    <book id="3">
        <name>三国演义</name>
        <author>罗贯中</author>
        <dynasty>元末明初</dynasty>
    </book>
        <book id="4">
        <name>水浒传</name>
        <author>施耐庵</author>
        <dynasty>元末明初</dynasty>
    </book>
</bookstore>
    编写对应java实体类Book:

package com.ldl.xml;
public class Book {
    
    private int id;
    private String name;
    private String author;
    private String dynasty;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getDynasty() {
        return dynasty;
    }
    public void setDynasty(String dynasty) {
        this.dynasty = dynasty;
    }
    @Override
    public String toString() {
        return "Book [id=" + id + ", name=" + name + ", author=" + author + ", dynasty=" + dynasty + "]";
    }
}

二、各解析方式及说明    

      接下来我们介绍具体的解析方法:

方法一、DOM(文档对象模型)解析方式
原理:将XML文档数据转换成一个DOM树形结构数据,使用DOM相关接口操作DOM树。

package com.ldl.xml;

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

import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
import javax.xml.parsers.ParserConfigurationException;  
  
import org.w3c.dom.Document;  
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ReadxmlByDom {

    private static DocumentBuilderFactory dbFactory = null;  
    private static DocumentBuilder db = null;  
    private static Document document = null;  
    private static List<Book> books = null;  
    static{  
        try {  
            dbFactory = DocumentBuilderFactory.newInstance();  
            db = dbFactory.newDocumentBuilder();  
        } catch (ParserConfigurationException e) {  
            e.printStackTrace();  
        }  
    }  
      
    public static List<Book> getBooks(String fileName) throws Exception{  
        document = db.parse(fileName);  
        NodeList bookList = document.getElementsByTagName("book");
        books = new ArrayList<Book>();  
        for(int i=0;i<bookList.getLength();i++){  
            Book book = new Book();  
            Node node = bookList.item(i);  
            NamedNodeMap namedNodeMap = node.getAttributes();  
            String id = namedNodeMap.getNamedItem("id").getTextContent();
            book.setId(Integer.parseInt(id));  
            NodeList cList = node.getChildNodes();  
            ArrayList<String> contents = new ArrayList<>();  
            for(int j=1;j<cList.getLength();j+=2){  
                Node cNode = cList.item(j);  
                String content = cNode.getFirstChild().getTextContent();  
                contents.add(content);  
            }  
              
            book.setName(contents.get(0));  
            book.setAuthor(contents.get(1));  
            book.setDynasty(contents.get(2));
            books.add(book);  
        }  
        return books;  
    }  
      
    public static void main(String args[]){  
        String fileName = "src/books.xml";
        System.out.println("---ReadXmlByDom---");
        try {  
            List<Book> list = ReadxmlByDom.getBooks(fileName);  
            for(Book book :list){  
                System.out.println(book);  
            }  
        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }     
}

运行效果:

      方法浅析:首先指定需要解析的XML文档,并转换为文档(Document)对象,然后利用文档对象获取节点(子节点),将获取到的值添加到封装好的Book对象中。

方法二、JDOM解析方式
原理:JDOM可以理解为Java语言专门用来读写XML的一种组件。

package com.ldl.xml;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class ReadXMLByJDom {

    private List<Book> books = null;
    private Book book = null;

    @SuppressWarnings("unchecked")
    public List<Book> getBooks(String fileName){
        SAXBuilder saxBuilder = new SAXBuilder();
        try {
            Document document = saxBuilder.build(new FileInputStream(fileName));
            Element rootElement = document.getRootElement();
            List<Element> bookList = rootElement.getChildren();
            books = new ArrayList<Book>();
            for(Element bookElement : bookList){
                book = new Book();
                List<Attribute> bookAttributes = bookElement.getAttributes();
                for(Attribute attribute : bookAttributes){
                    if(attribute.getName().equals("id")){
                        String id = attribute.getValue();
                        book.setId(Integer.parseInt(id));
                    }
                }
                List<Element> children = bookElement.getChildren();
                for(Element child : children){
                    if(child.getName().equals("name")){
                        String name = child.getValue();
                        book.setName(name);
                    }else if(child.getName().equals("author")){
                        String author = child.getValue();
                        book.setAuthor(author);
                    }else if(child.getName().equals("dynasty")){
                        String dynasty = child.getValue();
                        book.setDynasty(dynasty);
                    }
                }
                books.add(book);
                book = null;
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return books;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String fileName = "src/books.xml";
        System.out.println("---ReadXmlByJDom---");
        List<Book> books= new ReadXMLByJDom().getBooks(fileName);
        for(Book book : books){
            System.out.println(book);
        }
    }
}
运行效果:

方法浅析:首先指定需要解析的XML文档,并利用SAXBuilder解析器将其通过流的形式转换为文档(Document)对象,然后利用文档对象获取节点(子节点),将获取到的值添加到封装好的Book对象中。

方法三、DOM4j解析方式
原理:与DOM基本相似。

package com.ldl.xml;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ReadXMLByDom4j {

    private List<Book> bookList = null;
    private Book book = null;

    @SuppressWarnings("rawtypes")
    public List<Book> getBooks(File file){

        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(file);
            Element bookstore = document.getRootElement();
            Iterator storeit = bookstore.elementIterator();

            bookList = new ArrayList<Book>();
            while(storeit.hasNext()){

                book = new Book();
                Element bookElement = (Element) storeit.next();
                List<Attribute> attributes = bookElement.attributes();
                for(Attribute attribute : attributes){
                    if(attribute.getName().equals("id")){
                        String id = attribute.getValue();
                        book.setId(Integer.parseInt(id));
                    }
                }

                Iterator bookit = bookElement.elementIterator();
                while(bookit.hasNext()){
                    Element child = (Element) bookit.next();
                    String nodeName = child.getName();
                    if(nodeName.equals("name")){
                        String name = child.getStringValue();
                        book.setName(name);
                    }else if(nodeName.equals("author")){
                        String author = child.getStringValue();
                        book.setAuthor(author);
                    }else if(nodeName.equals("dynasty")){
                        String dynasty = child.getStringValue();
                        book.setDynasty(dynasty);
                    }
                }
                bookList.add(book);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return bookList;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        File file = new File("src/books.xml");
        System.out.println("---ReadXmlByDom4j---");
        List<Book> bookList = new ReadXMLByDom4j().getBooks(file);
        for(Book book : bookList){
            System.out.println(book);
        }
    }
}
运行效果:

方法浅析:与JDOM方法思路基本一致。

方法四、SAX解析方式
原理:SAX分析器通过事件触发的形式,实现对XML文档数据的访问和操作。

工具类:

package com.ldl.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 SAXParseHandler extends DefaultHandler{

    private List<Book> list;         
    private Book book;               
    private String content = null;   

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        list = new ArrayList<Book>();
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        if(qName.equals("book")){
            book = new Book();
            String id = attributes.getValue("id");
            book.setId(Integer.parseInt(id));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if(qName.equals("name")){
            book.setName(content);
        }else if(qName.equals("author")){
            book.setAuthor(content);
        }else if(qName.equals("dynasty")){
            book.setDynasty(content);
        }else if(qName.equals("book")){         
            list.add(book);
            book = null;
        }   
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        content = new String(ch, start, length);
    }

    public List<Book> getBooks(){
        return list;
    }
}
具体实现:

package com.ldl.xml;

import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class ReadXmlBySAX {

    private static List<Book> books = null;

    public List<Book> getBooks(String fileName) throws Exception{
        SAXParserFactory sParserFactory = SAXParserFactory.newInstance();
        SAXParser parser = sParserFactory.newSAXParser();

        SAXParseHandler handler = new SAXParseHandler();
        parser.parse(fileName, handler);
        return handler.getBooks();

    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            books = new ReadXmlBySAX().getBooks("src/books.xml");
            System.out.println("---ReadXmlBySAX---");
            for(Book book:books){
                System.out.println(book);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}
运行效果:

方法浅析:SAX解析器采用流式处理方式,每读取XML的一个根节点(子节点)都会触发事件,直到整个文档解析完毕。

       几种方法解析XML各有优劣,关于方法效率的对比,大家可以查阅资料深入研究,毕竟用到解析XML的项目相对较少,在此不做赘述。

猜你喜欢

转载自blog.csdn.net/ldllovegyh/article/details/83422021