xml文件解析,你该怎么选择,一文给你讲清楚

XML 简介

XML 指可扩展标记语言(EXtensible Markup Language), 是一种很像HTML的标记语言,但是XML用于传输和存储数据的.

XML的解析方式分有:(1)DOM解析;(2)SAX解析;(3)STAX解析;(4)JDOM解析;(5)DOM4J解析。其中前两种属于基础方法,是官方提供的平台无关的解析方式;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。

针对以下的XML 文件,分别采用以上提到的五种方式进行解析:



    
        grndpa
         75
        Writing brush
    
    
        grndma
        70
        Read book
    
    
        father
        48
        Play golf
    
    
        mom
        45
        Grow flowers
    
    
        son
        20
        Play basketball
    

DOM 解析

DOM模式解析XML,是把整个XML文档当成一个对象来处理,会先把整个文档读入到内存里。是基于树的结构,通常需要加载整文档和构造DOM树,然后才能开始工作。

 @Test
    public  void domTest() throws ParserConfigurationException, IOException, SAXException {
        //创建待解析的XML文件,并指定目标
        File file=new File("src/main/resources/xmlanalysisTest.xml");
        //1.创建DocumentBuilderFactory
        DocumentBuilderFactory documentBuilderFactory= DocumentBuilderFactory.newInstance();

        // 2.用工厂对象创建DocumentBuilder对象
        DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
       // 3.用DocumentBuilder对象将xml文件加载进内存,用Document对象接收
        Document document= documentBuilder.parse(file);
       // 4.获取到所有family节点,返回NodeList
        NodeList memberList= document.getElementsByTagName("memeber");

        // 5.循环遍历NodeList里的family节点
       /* for (int i=0; i

image

优点:

  • 允许应用程序对数据和结构做出更改。
  • 访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。
  • 整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能

缺点:

  • 整个 XML 文档必须一次性解析完,耗时。
  • 将整个文档调入内存(包括无用的节点),浪费时间和空间;

使用场合:文档较小,且需要修改文档内容

SAX 解析

SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。SAX处理的特点是基于事件流的。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。sax分析器在对xml文档进行分析时,触发一系列的事件,应用程序通过事件处理函数实现对xml文档的访问,因为事件触发是有时序性的,所以sax分析器提供的是一种对xml文档的顺序访问机制,对于已经分析过的部分,不能再重新倒回去处理。

SAX解析方式:逐行扫描文档,一边扫描一边解析。相比于DOM,SAX可以在解析文档的任意时刻停止解析解析,是一种速度更快,更高效的方法。

SAX 是推模式的,所有的操作在解析器自动控制下进行,所有事件都会处理,不管需不需要解析整个文档,解析器都会自动启动解析任务,然后按顺序向下解析,直到解析完成才终止。 简单说来,推模式,就是你把如何操作通通告诉解析器,之后,解析器自动去完成所有解析任务,你不能做任何干涉了。

public class FamilyHandler extends DefaultHandler {

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("解析XML 文件开始");
    }

    @Override
    public void endDocument() throws SAXException {
        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);
        if("member".equals(qName)){
            int length = attributes.getLength();

            //遍历属性

            for (int i=0;i

优点:

  • 访问能够立即进行,不需要等待所有数据被加载。
  • 只在读取数据时检查数据,不需要保存在内存中
  • 不需要将整个数据都加载到内存中,占用内存少
  • 允许注册多个Handler,可以用来解析文档内容,DTD约束等等。

缺点:

  • 需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。
  • 单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。
  • 不能随机访问 xml 文档,不支持原地修改xml。

适用于:文档较大,只需要读取文档数据。

STAX 解析

Java 6.0对XML支持的新特性有许多方面。比如StAX、针对XML-Web服务的Java架构(JAX-WS)2.0、针对XML绑定的API(JAXB)2.0、XML数字签名API,甚至还支持SQL:2003 'XML’数据类型。

StAX是Streaming API for XML的缩写,是一种针对XML的流式拉分析API。StAX是一个基于JAVA API用于解析XML文档,类似SAX解析器的方式

StAX 是拉模式的,可以由用户根据需要控制需要处理事件类型及何时终止解析任务,用户调用一次next(),解析器就进行一次向下解析,完全在用户的控制下进行解析操作,在需要的解析工作已经完成时,可以随时终止解析。简单来说,拉模式就像抽纸,随用随拉,需要时就拉一下,不需要时,它不会自动推出来。你可以一直拉把一盒抽纸拉完,也可以按自己需要只拉几张。

StAX的API可以读取和写入XML文档。

  @Test
    public void StaxTest() throws FileNotFoundException, XMLStreamException {
        //创建XML流工程
        XMLInputFactory factory = XMLInputFactory.newInstance();

        InputStream resourceAsStream = new FileInputStream("src/main/resources/xmlanalysisTest.xml");
        //创建XML事件读取流
        XMLEventReader reader = factory.createXMLEventReader(resourceAsStream);

        while (reader.hasNext()){
            XMLEvent event = reader.nextEvent();

            //如果是开始元素
            if (event.isStartElement()){
                //读取开始元素
                StartElement startElement = event.asStartElement();
                String name= startElement.getName().toString();

                // 获取属性
                Iterator iterator = startElement.getAttributes();
                while (iterator.hasNext()){
                    Attribute obj= (Attribute) iterator.next();
                    System.out.println(obj.getName() +":" +obj.getValue());
                }
                System.out.println("<" + name +">");
            }

            //如果是文本
            if (event.isCharacters()){
                //获取文本值
                String str= event.asCharacters().getData();
                if(!"".equals(str.trim())){
                    System.out.println(str);
                }
            }
        }
    }

应该使用的StAX解析器的时候:

  • 可以处理在自上而下线性方式的XML文档。
  • 文件并不深入嵌套。
  • 处理一个非常大的XML文档的DOM树会占用太多的内存。典型的DOM的实现使用10字节的存储器以表示XML的一个字节。
  • 要解决的问题涉及XML文档的一部分。
  • 数据是可用的,只要它是由解析器处理,这样StAX可以很好地用于所收到超过数据流的XML文档。

SAX的缺点

因为它是在一个处理的方式,而不是随机访问XML文档。

如果需要跟踪的数据分析器已经看到或更改项目的顺序,必须编写代码和数据存储以自己方式处理。

JDOM 解析

JDOM是处理xml的纯java api.使用具体类而不是接口.JDOM具有树的遍历,又有SAX的java规则.JDOM与DOM主要有两方面不同。

首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。

第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。

JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入XML文档(尽管它还可以将以前构造的DOM表示作为输入)。它包含一些转换器以将JDOM表示输出成SAX2事件流、DOM模型或XML文本文档。

 @Test
    public  void jbomTest() throws IOException, JDOMException {
        //(1)创建SAXBuilder对象
        SAXBuilder saxBuilder = new SAXBuilder();
        //(2)调用build方法获得Document对象
        Document document = saxBuilder.build(new FileInputStream("src/main/resources/xmlanalysisTest.xml"));
        //(3)获取根节点
        Element books = document.getRootElement();
        //(4)获取根节点的直接子节点集合
        List booksChildren = books.getChildren();
        //(5)遍历
        for(int i = 0; i < booksChildren.size(); i++){
            //获取book节点
            Element member = booksChildren.get(i);
            //获取属性的集合
            List attributes = member.getAttributes();
            //遍历属性
            for(Attribute attr : attributes){
                System.out.println("属性名:"+attr.getName()+"\t属性值:"+attr.getValue());
            }
        }
        System.out.println("--------------------------------------------");
        for(int i = 0; i < booksChildren.size(); i++){
            //获取book节点
            Element member = booksChildren.get(i);
            //获取book的子节点
            List children = member.getChildren();
            //遍历节点
            for(Element ele : children){
                System.out.println("节点名:"+ele.getName()+"\t节点值:"+ele.getValue());
            }
        }
    }

优点:

1、是基于树的处理xml的java api,把树加载到内存中.

2、没有向下兼容的限制,所以比DOM简单.

3、速度快.

4、具有SAX的java 规则.

缺点:

1、不能处理大于内存的文档.

2、JDOM表示XML文档逻辑模型,不能保证每个字节真正变换.

3、 针对实例文档不提供DTD与模式的任何实际模型.

4、 不支持于DOM中相应遍历包.

DOM4J 解析

DOM4J有更复杂的api,所以dom4j比jdom有更大的灵活性.DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.

先在maven中引入jar包:

 
    
        dom4j
        dom4j
        1.6.1
    
    

创建实体类

public class Family {
    private String id;

    private  String Seniority;

    private  String age;

    private  String hobby;

    public String getId() {
        return id;
    }

    public Family(String id, String seniority, String age, String hobby) {
        this.id = id;
        Seniority = seniority;
        this.age = age;
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Family{" +
                "id='" + id + ''' +
                ", Seniority='" + Seniority + ''' +
                ", age='" + age + ''' +
                ", hobby='" + hobby + ''' +
                '}';
    }



    public void setId(String id) {
        this.id = id;
    }

    public String getSeniority() {
        return Seniority;
    }

    public void setSeniority(String seniority) {
        Seniority = seniority;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

dom4j解析xml:

 @Test
    public  void dom4jTest() throws DocumentException {
        // 1.创建SAXReader对象,
        SAXReader saxReader = new SAXReader();

        //2.读取XML文件
        Document read = saxReader.read("src/main/resources/xmlanalysisTest.xml");

        //3.通过Document 对象获取根元素
        Element rootElement = read.getRootElement();

        //4. 通过根元素获取book
        //element() 和elements()都可以获取标签签名查找子元素
        List family = rootElement.elements("memeber") ;
        //5.遍历,每一个book标签转换为family类
        for(Element memeber: family){
            String Seniority=memeber.elementText("Seniority");
            String age = memeber.elementText("age");
            String hobby= memeber.elementText("hobby");

            String id = memeber.attributeValue("id");

            System.out.println(new Family(id,Seniority,age,hobby));
            System.out.println("=================================");
        }

    }
    

优点:

  • 大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
  • 支持XPath。查找节点特别快
  • 灵活性高。

缺点:

  • 大量的使用了接口,API复杂,理解难。
  • 移植性差。

解析方式对比

DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J。

JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出,但可移植。在小文档情况下还值得考虑使用DOM和JDOM.虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。

SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

总结:如果XML文档较大且不考虑移植性问题建议采用DOM4J;如果XML文档较小则建议采用JDOM;如果需要及时处理而不需要保存数据则考虑SAX

你可能感兴趣的:(java,xml)