xml中的常见解析技术

XML 两种解析方式简介

大名鼎鼎的 DOM

说它大名鼎鼎可是一点不为过,DOM 是 W3C 处理 XML 的标准 API,它是许多其它与 XML 处理相关的标准的基础,不仅是 Java,其它诸如 Javascript,PHP,MS .NET 等等语言都实现了该标准, 成为了应用最为广泛的 XML 处理方式。当然,为了能提供更多更加强大的功能,Java 对于 DOM 直接扩展工具类有很多,比如很多 Java 程序员耳熟能详的 JDOM,DOM4J 等等, 它们基本上属于对 DOM 接口功能的扩充,保留了很多 DOM API 的特性,许多原本的 DOM 程序员甚至都没有任何障碍就熟练掌握了另外两者的使用,直观、易于操作的方式使它深受广大 Java 程序员的喜爱。

绿色环保的 SAX

SAX 的应运而生有它特殊的需要,为什么说它绿色环保呢,这是因为 SAX 使用了最少的系统资源和最快速的解析方式对 XML 处理提供了支持。 但随之而来繁琐的查找方式也给广大程序员带来许多困扰,常常令人头痛不已,同时它对 XPath 查询功能的支持,令人们对它又爱又恨。

它两的区别?

DOM

优缺点:实现 W3C 标准,有多种编程语言支持这种解析方式,并且这种方法本身操作上简单快捷,十分易于初学者掌握。其处理方式是将 XML 整个作为类似树结构的方式读入内存中以便操作及解析,因此支持应用程序对 XML 数据的内容和结构进行修改,但是同时由于其需要在处理开始时将整个 XML 文件读入到内存中去进行分析,因此其在解析大数据量的 XML 文件时会遇到类似于内存泄露以及程序崩溃的风险,请对这点多加注意。

适用范围:小型 XML 文件解析、需要全解析或者大部分解析 XML、需要修改 XML 树内容以生成自己的对象模型

SAX

SAX 从根本上解决了 DOM 在解析 XML 文档时产生的占用大量资源的问题。其实现是通过类似于流解析的技术,通读整个 XML 文档树,通过事件处理器来响应程序员对于 XML 数据解析的需求。由于其不需要将整个 XML 文档读入内存当中,它对系统资源的节省是十分显而易见的,它在一些需要处理大型 XML 文档以及性能要求较高的场合有起了十分重要的作用。支持 XPath 查询的 SAX 使得开发人员更加灵活,处理起 XML 来更加的得心应手。但是同时,其仍然有一些不足之处也困扰广大的开发人员:首先是它十分复杂的 API 接口令人望而生畏,其次由于其是属于类似流解析的文件扫描方式,因此不支持应用程序对于 XML 树内容结构等的修改,可能会有不便之处。SAX因为是流解析式的,解析过程中不能回退,如果需查找之前的还需重新解析xml。且是按顺序解析的,不支持随机解析

适用范围:大型 XML 文件解析、只需要部分解析或者只想取得部分 XML 树内容、有 XPath 查询需求、有自己生成特定 XML 树对象模型的需求

应用示例

下面给出一段用于解析的 XML 片段:

清单 1. XML 片段
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="001">
     <title>Harry Potter</title>
     <author>J K. Rowling</author>
  </book>
  <book id="002">
     <title>Learning XML</title>
     <author>Erik T. Ray</author>
  </book>
</books>

DOM 解析 XML

Java 中的 DOM 接口简介: JDK 中的 DOM API 遵循 W3C DOM 规范,其中 org.w3c.dom 包提供了 Document、DocumentType、Node、NodeList、Element 等接口, 这些接口均是访问 DOM 文档所必须的。我们可以利用这些接口创建、遍历、修改 DOM 文档。

javax.xml.parsers 包中的 DoumentBuilder 和 DocumentBuilderFactory 用于解析 XML 文档生成对应的 DOM Document 对象。

javax.xml.transform.dom 和 javax.xml.transform.stream 包中 DOMSource 类和 StreamSource 类,用于将更新后的 DOM 文档写入 XML 文件。

下面给出一个运用 DOM 解析 XML 的例子:

import java.io.File; 
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.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.SAXException; 
 
public class DOMParser { 
  DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); 
  //Load and parse XML file into DOM 
  public Document parse(String filePath) { 
     Document document = null; 
     try { 
        //DOM parser instance 
        DocumentBuilder builder = builderFactory.newDocumentBuilder(); 
        //parse an XML file into a DOM tree 
        document = builder.parse(new File(filePath)); 
     } catch (ParserConfigurationException e) { 
        e.printStackTrace();  
     } catch (SAXException e) { 
        e.printStackTrace(); 
     } catch (IOException e) { 
        e.printStackTrace(); 
     } 
     return document; 
  } 
    
  public static void main(String[] args) { 
        DOMParser parser = new DOMParser(); 
        Document document = parser.parse("books.xml"); 
        //get root element 
        Element rootElement = document.getDocumentElement(); 
 
        //traverse child elements 
        NodeList nodes = rootElement.getChildNodes(); 
        for (int i=0; i < nodes.getLength(); i++) 
        { 
           Node node = nodes.item(i); 
           if (node.getNodeType() == Node.ELEMENT_NODE) {   
              Element child = (Element) node; 
              //process child element 
           } 
        } 
 
        NodeList nodeList = rootElement.getElementsByTagName("book"); 
        if(nodeList != null) 
        { 
           for (int i = 0 ; i < nodeList.getLength(); i++) 
           { 
              Element element = (Element)nodeList.item(i); 
              String id = element.getAttribute("id"); 
           } 
        } 
  } 
}

在上面的例子中,DOMParser 的 Parse() 方法负责解析 XML 文件并生成对应的 DOM Document 对象。其中 DocumentBuilderFactory 用于生成 DOM 文档解析器以便解析 XML 文档。 在获取了 XML 文件对应的 Document 对象之后,我们可以调用一系列的 API 方便的对文档对象模型中的元素进行访问和处理。 需要注意的是调用 Element 对象的 getChildNodes() 方法时将返回其下所有的子节点,其中包括空白节点,因此需要在处理子 Element 之前对节点类型加以判断。

可以看出 DOM 解析 XML 易于开发,只需要通过解析器建立起 XML 对应的 DOM 树型结构后便可以方便的使用 API 对节点进行访问和处理,支持节点的删除和修改等。 但是 DOM 解析 XML 文件时会将整个 XML 文件的内容解析成树型结构存放在内存中,因此不适合用 DOM 解析很大的 XML 文件。

SAX 解析 XML

与 DOM 建立树形结构的方式不同,SAX 采用事件模型来解析 XML 文档,是解析 XML 文档的一种更快速、更轻量的方法。 利用 SAX 可以对 XML 文档进行有选择的解析和访问,而不必像 DOM 那样加载整个文档,因此它对内存的要求较低。 但 SAX 对 XML 文档的解析为一次性读取,不创建任何文档对象,很难同时访问文档中的多处数据。

下面是一个 SAX 解析 XML 的例子:

import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax.helpers.XMLReaderFactory; 
 
public class SAXParser { 
 
  class BookHandler extends DefaultHandler { 
     private List<String> nameList; 
     private boolean title = false; 
   
     public List<String> getNameList() { 
        return nameList; 
     } 
     // Called at start of an XML document 
     @Override 
     public void startDocument() throws SAXException { 
        System.out.println("Start parsing document..."); 
        nameList = new ArrayList<String>(); 
     } 
     // Called at end of an XML document 
     @Override 
     public void endDocument() throws SAXException {  
        System.out.println("End");  
     } 
      
     /** 
      * Start processing of an element. 
      * @param namespaceURI  Namespace URI 
      * @param localName  The local name, without prefix 
      * @param qName  The qualified name, with prefix 
      * @param atts  The attributes of the element 
      */ 
     @Override 
     public void startElement(String uri, String localName, String qName, 
        Attributes atts) throws SAXException { 
        // Using qualified name because we are not using xmlns prefixes here. 
        if (qName.equals("title")) { 
           title = true; 
        } 
     } 
   
     @Override 
     public void endElement(String namespaceURI, String localName, String qName) 
        throws SAXException { 
        // End of processing current element 
        if (title) { 
           title = false; 
        } 
     } 
            
     @Override 
     public void characters(char[] ch, int start, int length) { 
        // Processing character data inside an element 
        if (title) { 
           String bookTitle = new String(ch, start, length); 
           System.out.println("Book title: " + bookTitle); 
           nameList.add(bookTitle); 
        } 
     } 
            
  } 
    
  public static void main(String[] args) throws SAXException, IOException { 
     XMLReader parser = XMLReaderFactory.createXMLReader(); 
     BookHandler bookHandler = (new SAXParser()).new BookHandler(); 
     parser.setContentHandler(bookHandler); 
     parser.parse("books.xml"); 
     System.out.println(bookHandler.getNameList()); 
  } 
}

SAX 解析器接口和事件处理器接口定义在 org.xml.sax 包中。主要的接口包括 ContentHandler、DTDHandler、EntityResolver 及 ErrorHandler。 其中 ContentHandler 是主要的处理器接口,用于处理基本的文档解析事件;DTDHandler 和 EntityResolver 接口用于处理与 DTD 验证和实体解析相关的事件; ErrorHandler 是基本的错误处理接口。DefaultHandler 类实现了上述四个事件处理接口。上面的例子中 BookHandler 继承了 DefaultHandler 类, 并覆盖了其中的五个回调方法 startDocument()、endDocument()、startElement()、endElement() 及 characters() 以加入自己的事件处理逻辑。

原文地址:https://www.cnblogs.com/nyhhd/p/13410290.html