编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

JAVA解析XML的四种方式优缺点对比

gowuye 2024-04-04 11:54 7 浏览 0 评论

1、示例XML为hello.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book id="1">    <!-- id="1"---属性名和属性值 -->
        <name>天龙八部</name>
        <author>金庸</author>
        <year>2014</year>
        <price>88</price>
    </book>
    <book id="2">
        <name>鹿鼎记</name>
        <year>2015</year>
        <price>66</price>
        <language>中文</language>
    </book>
    <book id="3">
        <name>射雕英雄传</name>
        <author>金庸</author>
        <year>2016</year>
        <price>44</price>
    </book> 
</bookstore>

DOM(Document Object Model)解析

优点

  1. 允许应用程序对数据和结构做出更改
  2. 访问是双向的,可以在任何时候在树中上、下导航获取、操作任意部分的数据

缺点

解析XML文档的需要加载整个文档来构造层次结构,消耗内存资源大。

应用范围

遍历能力强,常应用于XML文档需要频繁改变的服务中。

解析步骤

  1. 创建一个 DocumentBuilderFactory 对象
  2. 创建一个 DocumentBuilder 对象
  3. 通过 DocumentBuilder 的 parse() 方法加载 XML 到当前工程目录下
  4. 通过 getElementsByTagName() 方法获取所有 XML 所有节点的集合
  5. 遍历所有节点
  6. 通过 item() 方法获取某个节点的属性
  7. 通过 getNodeName() 和 getNodeValue() 方法获取属性名和属性值
  8. 通过 getChildNodes() 方法获取子节点,并遍历所有子节点
  9. 通过 getNodeName() 和 getTextContent() 方法获取子节点名称和子节点值
package Paint;

import java.io.IOException;

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;
import org.xml.sax.SAXException;

public class DOMTest {
    public static void main(String[] args) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder(); 
            Document document = db.parse("./src/Paint/hello.xml");  
            NodeList bookList = document.getElementsByTagName("book");	//节点集

            int bookCnt = bookList.getLength();
            System.err.println("一共获取到" + bookCnt +"本书");

            for(int i=0; i<bookCnt; i++){
                Node book = bookList.item(i);
                NamedNodeMap attrs = book.getAttributes();
                for(int j=0; j<attrs.getLength(); j++){
                    Node attr = attrs.item(j);
                    System.err.println(attr.getNodeName()+"---"+attr.getNodeValue());//id
                
                }

                NodeList childNodes = book.getChildNodes();
                for(int k=0; k<childNodes.getLength(); k++){
                    if(childNodes.item(k).getNodeType() == Node.ELEMENT_NODE){            
                        System.out.println(childNodes.item(k).getNodeName()+"---" + childNodes.item(k).getTextContent());                    
                    }
                }
            }
        } catch (ParserConfigurationException e) {           
            e.printStackTrace();
        } catch (SAXException e) {            
            e.printStackTrace();
        } catch (IOException e) {           
            e.printStackTrace();
        }
    }
}

SAX(Simple API for XML)解析

优点

  1. 不需要等待所有的数据被处理,解析就可以开始
  2. 只在读取数据时检查数据,不需要保存在内存中
  3. 可以在某一个条件满足时停止解析,不必要解析整个文档
  4. 效率和性能较高,能解析大于系统内存的文档

缺点

  1. 解析逻辑复杂,需要应用层自己负责逻辑处理,文档越复杂程序越复杂
  2. 单向导航,无法定位文档层次,很难同时同时访问同一文档的不同部分数据,不支持 XPath

解析步骤

  1. 获取一个 SAXParserFactory 的实例
  2. 通过 factory() 获取 SAXParser 实例
  3. 创建一个 handler() 对象
  4. 通过 parser 的 parse() 方法来解析 XML

SAXTest.java

package Paint;

import java.io.IOException;

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

import org.xml.sax.SAXException;

public class SAXTest {

    public static void main(String[] args) {
        // 获取实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            SAXParserHandler handler = new SAXParserHandler();
            parser.parse("./src/Paint/hello.xml", handler);

            System.err.println("共有"+ handler.getBookList().size()+ "本书");
            for(Book book : handler.getBookList()){             
                System.out.println(book.getName());
                System.out.println("id=" + book.getId());
                System.out.println(book.getAuthor());
                System.out.println(book.getYear());
                System.out.println(book.getPrice());
                System.out.println(book.getLanguage());
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SAXParserHandler.java

package Paint;

import java.util.ArrayList;

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

public class SAXParserHandler extends DefaultHandler {
    String value = null;
    Book book = null;
    private ArrayList<Book> bookList = new ArrayList<Book>();

    public ArrayList<Book> getBookList() {
        return bookList;
    }
    /*
     * XML 解析开始
     */
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("xml 解析开始");
    }

    /*
     * XML 解析结束
     */
    public void endDocument() throws SAXException {  
        super.endDocument();
        System.out.println("xml 解析结束");
    }

    /*
     * 解析 XML 元素开始
     */
    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();

            for(int i=0; i<attributes.getLength();i++){
                System.out.println(attributes.getQName(i)+"---"+attributes.getValue(i));
                if(attributes.getQName(i).equals("id")){
                    book.setId(attributes.getValue(i));
                }               
            }
        }else if(!qName.equals("bookstore")){
            System.out.print("节点名:"+ qName + "---");    
        }
    }

    /*
     *解析 XML 元素结束
     */
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
     
        super.endElement(uri, localName, qName);
        if(qName.equals("book")){
            bookList.add(book);
            book = null;
        }
        else if(qName.equals("name")){          
            book.setName(value);
        }else if(qName.equals("year")){
            book.setYear(value);
        }else if(qName.equals("author")){
            book.setAuthor(value);
        }else if(qName.equals("price")){
            book.setPrice(value);
        }else if(qName.equals("language")){
            book.setLanguage(value);
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);

        // 获取节点值数组
        value = new String(ch, start, length);
        if(!value.trim().equals("")){
            System.out.println("节点值:"+value);
        }
    }
}

JDOM 解析

需要引入 jdom.jar

特征

  1. 仅使用具体类,而不使用接口
  2. API 大量使用了 Collections 类

解析步骤

  1. 创建一个 SAXBuilder 的对象
  2. 创建一个输入流,将 xml 文件加载到输入流中
  3. 通过 saxBuilder 的 build()方法,将输入流加载到 saxBuilder 中
  4. 通过 document 对象获取 xml 文件的根节点
  5. 获取根节点下的子节点的 List 集合
package Paint;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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 JDOMTest {
    private static ArrayList<Book> booksList = new ArrayList<Book>();
   
    public static void main(String[] args) {
        SAXBuilder saxBuilder = new SAXBuilder();
        InputStream in;
        try {
            in = new FileInputStream("./src/Paint/hello.xml");
            InputStreamReader isr = new InputStreamReader(in, "UTF-8");
           
            Document document = saxBuilder.build(isr);         
            Element rootElement = document.getRootElement();           
            List<Element> bookList = rootElement.getChildren();
          
            for (Element book : bookList) {
                Book bookEntity = new Book();
               
                List<Attribute> attrList = book.getAttributes();
               
                for (Attribute attr : attrList) {                   
                    String attrName = attr.getName();            
                    String attrValue = attr.getValue();
                    System.out.println( attrName + "----" + attrValue);
                    if (attrName.equals("id")) {
                        bookEntity.setId(attrValue);
                    }
                }
                // 对book节点的子节点的节点名以及节点值的遍历
                List<Element> bookChilds = book.getChildren();
                for (Element child : bookChilds) {
                    System.out.println(child.getName() + "----"+ child.getValue());
                    if (child.getName().equals("name")) {
                        bookEntity.setName(child.getValue());
                    }
                    else if (child.getName().equals("author")) {
                        bookEntity.setAuthor(child.getValue());
                    }
                    else if (child.getName().equals("year")) {
                        bookEntity.setYear(child.getValue());
                    }
                    else if (child.getName().equals("price")) {
                        bookEntity.setPrice(child.getValue());
                    }
                    else if (child.getName().equals("language")) {
                        bookEntity.setLanguage(child.getValue());
                    }
                }
               
                booksList.add(bookEntity);
                bookEntity = null;
                System.out.println(booksList.size());
                System.out.println(booksList.get(0).getId());
                System.out.println(booksList.get(0).getName());
                
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

DOM4J(Document Object Model for Java)解析

需要引入 dom4j-1.6.1.jar

优点

  1. 性能很好
  2. 大量使用 Java 集合类,开发简便,同时也提供了一些提高性能的代替方法
  3. 支持 XPath

缺点

  1. API 比较复杂

步骤

  1. 创建 SAXReader 的对象 reader
  2. 通过 reader 对象的 read() 方法加载 books.xml 文件,获取 document 对象
  3. 通过 document 对象获取根节点 bookstore
  4. 通过 element 对象的 elementIterator() 获取迭代器
  5. 遍历迭代器,获取根节点中的信息
  6. 获取 book 的属性名和属性值
  7. 通过 book 对象的 elementIterator() 获取节点元素迭代器
  8. 遍历迭代器,获取子节点中的信息
  9. 获取节点名和节点值
package Paint;

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 DOM4JTest {
    
    public static void main(String[] args) {
        ArrayList<Book> bookList = new ArrayList<Book>();
        SAXReader reader = new SAXReader();
        try {            
            Document document = reader.read(new File("./src/Paint/hello.xml"));
            Element bookStore = document.getRootElement();
            Iterator it = bookStore.elementIterator();
            while (it.hasNext()) {            

                Element book = (Element) it.next();
                Book bookData = new Book();             
                List<Attribute> bookAttrs = book.attributes();
                for (Attribute attr : bookAttrs) {
                    System.out.println(attr.getName() + "---" + attr.getValue());

                    if(attr.getName().equals("id")){
                        bookData.setId(attr.getValue());
                    }
                }               
                Iterator itt = book.elementIterator();

                while (itt.hasNext()) {
                    Element bookChild = (Element) itt.next();
                   
                    System.out.println(bookChild.getName()+ "---" + bookChild.getText());

                    if(bookChild.getName().equals("name")){
                        bookData.setName(bookChild.getText());
                    }else if(bookChild.getName().equals("author")){
                        bookData.setAuthor(bookChild.getText());
                    }else if(bookChild.getName().equals("year")){
                        bookData.setYear(bookChild.getText());
                    }else if(bookChild.getName().equals("price")){
                        bookData.setPrice(bookChild.getText());
                    }else if(bookChild.getName().equals("language")){
                        bookData.setLanguage(bookChild.getText());
                    }
                }               
                // 遍历完一个节点,将该节点信息添加到列表中
                bookList.add(bookData);

            }
        } catch (DocumentException e) {

            e.printStackTrace();
        }
        
        // 输出保存在内存中XML信息
        for(Book book:bookList){
            System.out.println(book.getName());
            System.out.println("id=" + book.getId());
            System.out.println(book.getAuthor());
            System.out.println(book.getYear());
            System.out.println(book.getPrice());
            System.out.println(book.getLanguage());
        }
    }
}



相关推荐

爱上开源之golang入门至实战第四章-切片(Slice)

前言Go数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可...

Go语言入门必知教程-切片

切片是一种灵活的和可扩展的数据结构,用于实现和管理数据集。切片由多个元素组成,所有元素都是相同类型的。切片是动态数组的一部分,可以根据需要进行增长和收缩。与数组一样,切片也可以索引。切片具有容量和长度...

Go语言基础-切片

切片是什么?切片是Go语言的一种数据结构。和数组相似,不过切片可以在它的结尾增加更多的元素。这样可变长度在实际编程中更为有用。声明切片切片的声明和数组也很相似,只是声明切片时不需要指定大小。例:va...

5分钟掌握GO中切片的基本使用方法

最近Golang越来越火,不少小伙伴都纷纷开始学习Golang,但对于原先为C++或者JAVA的同学,用习惯了数据、list、vector等,会对Go的切片slice不习惯,下面整理出go中slice...

揭秘 Go 切片(Slice)的秘密

当向切片添加新参数时,底层数组会发生什么变化?它会扩展以容纳更多元素吗?在这篇文章中,我们将深入探讨切片的内部工作原理,以及如何利用这些知识来进行更好的内存管理和性能优化。具体而言,我们将探索Go...

【Go语言slice详解】深入掌握Go语言中的slice类型及常用操作!

Go语言中的slice(切片)是一种非常方便的数据结构,可以动态地增加或减少其元素数量,且可以访问底层数组的任意一个子序列。本文将对Go语言中的slice进行详细的讲解。Slice的定义在Go语言中,...

掌握GO中的Slice,这就够了

最近Golang越来越火,不少小伙伴都纷纷开始学习Golang,但对于原先为C++或者JAVA的同学,用习惯了数据、list、vector等,会对Go的切片slice不习惯,下面整理出go中slice...

golang2021面向对象(26)Go语言类型内嵌和结构体内嵌

结构体可以包含一个或多个匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型也就是字段的名字。匿名字段本身可以是一个结构体类型,即结构体可以包含内嵌结构体。?可以粗略地将这个...

2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内

2022-11-13:以下go语言代码中,如何获取结构体列表以及结构体内的指针方法列表?以下代码应该返回{"S1":["M1","M2"],"S...

Go语言文件和目录操作

文件和目录操作概述一、文件和目录操作概述在计算机中,文件和目录是存储数据的重要方式。在Go语言中,我们可以使用os和io/ioutil包提供的函数和结构体来进行文件和目录操作。本文将详细介绍Go语言中...

跟我一起学习go语言(五)golang中结构体的初始化方法

1、自定义一个结构体typeVertexstruct{X,Yfloat64}2、初始化方法-指针:rect1:=new(Vertex)rect2:=&Vertex...

Go复合数据类型:结构体

一种通用的、对实体对象进行聚合抽象的能力,在Go中,提供这种聚合抽象能力的类型是结构体类型,也就是struct。自定义一个新类型在Go中,我们自定义一个新类型一般有两种方法。第一种是类型定义...

Go语言基础:方法

导读在阅读本文章前,假定你具备如下能力:?已掌握结构体1.方法1.1方法的概念在理解程序中方法的概念时,我们先看看现实中的一些情况,这样相对比较好理解一些。在农村的朋友可能会知道,在医疗落后的情况...

为什么 Go 语言 struct 要使用 tags

在Go语言中,struct是一种常见的数据类型,它可以用来表示复杂的数据结构。在struct中,我们可以定义多个字段,每个字段可以有不同的类型和名称。除了这些基本信息之外,Go还提供了s...

一文带你掌握掌握 Golang结构体与方法

1.Golang结构体的概念及定义结构体是Golang中一种复合类型,它是由一组具有相同或不同类型的数据字段组成的数据结构。结构体是一种用户自定义类型,它可以被用来封装多个字段,从而实现数据的...

取消回复欢迎 发表评论: