美文网首页我爱编程
Java XML文档解析

Java XML文档解析

作者: d3f59bfc7013 | 来源:发表于2018-04-12 14:36 被阅读0次

    导读:XML文档解析是Java框架的基础技术之一。主流的的框架都采用XML文件来存储配置信息,然后通过解析它,将其分解成各种元素并用这些元素来实例化Configuration类。Java库提供两种XML解析器,分别是DOM解析和SAX解析。


    XML文件解析器介绍

    • DOM解析(Document Object Model),是树形解析,它是将读入的XML文件转换成树结构。
    • SAX解析(Simple API for XML),是流机制解析,它是在读入XML文件时候生成相应的时间。

    区别: DOM解析必须在解析之前将整个文档装入内存,处理大型文件时候,性能低,适合XML随机访问。SAX解析,事件驱动,它顺序读取XML文件,不需要一次全部载入整个文件,当遇到文件开头、文档结束、标签开头或者标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合顺序访问。

    DOM和SAX解析实例

    XML文档准备,books.xml

    <?xml version="1.0" encoding="UTF-8"?>  
    <bookstore>  
        <book id="1">  
            <name>Java 核心技术</name>  
            <author>Cornell </author>  
            <year>2014</year>  
            <price>89</price>  
        </book>  
        <book id="2">  
            <name>深入浅出MyBatis</name>  
            <author>杨开振</author>  
            <year>2016</year>  
            <price>69</price>  
        </book>  
        <book id="3">  
            <name>Java RESTful Web Service实战</name>  
            <author>韩陆</author>  
            <year>2016</year>  
            <price>59</price>  
        </book>  
    </bookstore>  
    

    XML对应java类

    /**
    * @author gethin
    * @version 创建时间:2018年4月8日 下午2:17:51
    * 类说明
    */
    public class Book {
        private int id;
        private String name;
        private String author;
        private int year;
        private double price;
        @Override
        public String toString() {
            return "Book [id=" + id + ", name=" + name + ", author=" + author + ", year=" + year + ", price=" + price + "]";
        }
        getter,setter省略
    }
    
    

    DOM解析

    要读入一个XML文档,首先需要一个DocumentBuilder对象,可以从DocumentBuilderFactory工厂类中得到这个对象。

    DocumentBuilderFactory dBuilderFactory =DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder =dBuilderFactory.newDocumentBuilder();
    

    然后可从文件中读入某个文档

    File f=...
    Document doc=dBuilder.parse(f);
    

    或者用一个URL

    URL u=...
    Document doc=dBuilder.parse(u);
    

    以books.xml文档为例,用DOM解析读取整个文档。

    /**
    * @author gethin
    * @version 创建时间:2018年4月8日 下午3:17:04
    * 类说明
    */
    public class ReadXMLByDOM {
        private static DocumentBuilderFactory dBuilderFactory = null;
        private static DocumentBuilder dBuilder = null;
        private static Document document = null;
        private static List<Book> books = null;
        static {
            try {
                /**
                 * 要读入一个XML文档,首先要有一个DocumentBuilder对象 可以从DocumentBuilderFactory中得到这个对象
                 */
                dBuilderFactory = DocumentBuilderFactory.newInstance();
                dBuilder = dBuilderFactory.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public static List<Book> listBooks(String filename) throws SAXException, IOException {
            List<Book> books=new ArrayList<Book>();
            // 可通过DocumentBuilder对象的parse()方法读入整个文档
            Document document = dBuilder.parse(filename);
            // 获得根节点,books.xml对应的就是bookstore节点
            Element root = document.getDocumentElement();
            // 输出根节点的名字,bookstore
            System.out.println(root.getTagName());
            // 获得所有的book节点
            NodeList children = root.getChildNodes();
            //循环遍历各个book节点
            for (int i = 0; i < children.getLength(); i++) {
                //获得第i个book节点
                Node child = children.item(i);
                //用来存储第i个节点的内容
                List<String> bookAttrbuteContent=new ArrayList<String>();
                Book book=new Book();
                /**
                 * 这里要注意的是dom会把两个节点之间的空白字符也当做节点 要判断是否是子元素,
                 * 而不是空白字符,这个可以参照 《Java核心技术卷 二》的解析XML文档章节,有详细的解释
                 */
                
                if (child instanceof Element) {
                    Element childElement = (Element) child;
                    int bookId=Integer.parseInt(childElement.getAttribute("id"));
                    System.out.println(bookId);
                    book.setId(bookId);
                    NodeList bookAttrbuteList = childElement.getChildNodes();
                    // 循环遍历book节点的各个子节点,如name,author...
                    for (int j = 0; j < bookAttrbuteList.getLength(); j++) {
                        Node bookAttrbute = bookAttrbuteList.item(j);
                        if (bookAttrbute instanceof Element) {
                            String content=bookAttrbute.getTextContent().trim();
                            System.out.println(
                                    ((Element) bookAttrbute).getTagName() + ":" + content);
                            bookAttrbuteContent.add(content);
                        }
                    }
                    book.setName(bookAttrbuteContent.get(0));
                    book.setAuthor(bookAttrbuteContent.get(1));
                    book.setYear(Integer.parseInt(bookAttrbuteContent.get(2)));
                    book.setPrice(Integer.parseInt(bookAttrbuteContent.get(3)));
                    books.add(book);
                }
            }
            return books;
        }
    
        public static void main(String args[]) {
            String fileName = "./src/main/java/com/gethin/xmlparser/books.xml";
            try {
                List<Book> books=ReadXMLByDOM.listBooks(fileName);
                for(Book book:books) {
                    System.out.println(book);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    

    运行截图

    DOM解析books.xml运行截图

    SAX解析

    DOM解析器完整地读入了XML文档,将其转换为一个树形的结构。对于大多数应用,DOM都运行的很好。但是如果文档很大,而且处理算法又很简单。那么DOM解析可能效率非常低下,此时可以使用SAX解析。
    SAX要解析XML文件首先要生成SAXParser,SAXParser可以通过SAXParserFactory工厂类生成。

    SAXParserFactory saxParserFactory= SAXParserFactory.newInstance();
    SAXParser saxParser=saxParserFactory.newSAXParser();
    

    然后就可以处理XML文档了

    saxParser.parse(source,handler)
    

    source可以是一个文件,一个URL字符串或者一个输入流。handler属于DefaultHandler的一个子类。以下通过SAX来解析books.xml

    /**
    * @author gethin
    * @version 创建时间:2018年4月12日 上午10:49:57
    * 类说明
    */
    class BookXMLParseHandler extends DefaultHandler {
        private List<Book> list; // 存放解析到的book数组
        private Book book; // 存放当前解析的book
        private String content = null; // 存放当前节点值
    
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
    //      System.out.println("开始解析xml文件");
            list = new ArrayList<Book>();
        }
    
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            super.endDocument();
    //      System.out.println("xml文件解析完毕");
        }
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            // 当节点名为book时,获取book的属性id
            if (qName.equals("book")) {
                book = new Book();
                String id = attributes.getValue("id");// System.out.println("id值为"+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);
                // System.out.println("书名"+content);
            } else if (qName.equals("author")) {
                book.setAuthor(content);
                // System.out.println("作者"+content);
            } else if (qName.equals("year")) {
                book.setYear(Integer.parseInt(content));
                // System.out.println("年份"+content);
            } else if (qName.equals("price")) {
                book.setPrice(Double.parseDouble(content));
                // System.out.println("价格"+content);
            } else if (qName.equals("book")) { // 当结束当前book解析时,将该book添加到数组后置为空,方便下一次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;
        }
    }
    
    public class ReadXMLBySAX {
        private static SAXParserFactory saxParserFactory;
        private static SAXParser saxParser;
        static {
            try {
                saxParserFactory = SAXParserFactory.newInstance();
                saxParser = saxParserFactory.newSAXParser();
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }
    
        public static List<Book> listBooks(String fileName) throws SAXException, IOException {
            BookXMLParseHandler handler = null;
            handler = new BookXMLParseHandler();
            saxParser.parse(fileName, handler);
            return handler.getBooks();
        }
    
        public static void main(String args[]) {
            String fileName = "./src/main/java/com/gethin/xmlparser/books.xml";
            try {
                List<Book> books = ReadXMLBySAX.listBooks(fileName);
                for (Book book : books) {
                    System.out.println(book);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

    运行截图


    SAX解析XML运行截图

    相关文章

      网友评论

        本文标题:Java XML文档解析

        本文链接:https://www.haomeiwen.com/subject/vagxkftx.html