Java中使用jaxp进行sax解析_动力节点Java学院整理

 更新时间:2017年08月02日 10:40:31   投稿:mrr  
使用SAX的优势在于其解析速度较快,相对于DOM而言占用内存较少。这篇文章主要介绍了Java中使用jaxp进行sax解析,需要的朋友可以参考下

SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程序。使用SAX的优势在于其解析速度较快,相对于DOM而言占用内存较少。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说,在处理某个标签的时候,比如在startElement方法中,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。所以相对DOM而言,SAX处理XML文档没有DOM方便,SAX处理的过程相对DOM而言也比较复杂。

        SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:

解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。

解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。

备注说明:SAX API中主要有四种处理事件的接口,它们分别是ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler 

 这里使用最多的就是ContentHandler,仔细阅读 API文档,了解常用方法:startElement、endElement、characters等

 1.startElement方法说明

void startElement(String uri, 
     String localName, 
     String qName, 
     Attributes atts) 
     throws SAXException 

方法说明:  

解析器在 XML 文档中的每个元素的开始调用此方法;对于每个 startElement 事件都将有相应的 endElement 事件(即使该元素为空时)。所有元素的内容都将在相应的 endElement 事件之前顺序地报告。   

参数说明:  

uri - 名称空间 URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串  
localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串  
qName - 限定名(带有前缀),如果限定名不可用,则为空字符串  
atts - 连接到元素上的属性。如果没有属性,则它将是空 Attributes 对象。在 startElement 返回后,此对象的值是未定义的  

 2.endElement方法说明

void endElement(String uri, 

    String localName, 
    String qName) 
    throws SAXException接收元素结束的通知。 

SAX 解析器会在 XML 文档中每个元素的末尾调用此方法;对于每个 endElement 事件都将有相应的 startElement 事件(即使该元素为空时)。    

参数:  

uri - 名称空间 URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串  
localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串  
qName - 限定的 XML 名称(带前缀),如果限定名不可用,则为空字符串  

3.characters方法

void characters(char[] ch, 
    int start, 
    int length) 
    throws SAXException 

接收字符数据的通知,可以通过new String(ch,start,length)构造器,创建解析出来的字符串文本.  

参数:  

ch - 来自 XML 文档的字符  
start - 数组中的开始位置  
length - 从数组中读取的字符的个数   

其它方法请参考api数据

下面我们就具体讲解sax解析的操作.

一.我们通过XMLReaderFactory、XMLReader完成,步骤如下

1.通过XMLReaderFactory创建XMLReader对象  

XMLReader reader = XMLReaderFactory.createXMLReader();  

2. 设置事件处理器对象  

reader.setContentHandler(new MyDefaultHandler()); 

3.读取要解析的xml文件  

FileReader fileReader =new FileReader(new File("src\\sax\\startelement\\web.xml")); 

4.指定解析的xml文件  

reader.parse(new InputSource(fileReader)); 

案例:通过案例对uri、localName、qName和attribute参数有更加深入的了解

1.首先创建要解析的web.xml文件,内容如下

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" 
 xmlns:csdn="http://java.sun.com/xml/ns/javaee" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
 <csdn:display-name></csdn:display-name>  
</web-app> 
<!-- 
uri - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。 
xml namespace-xmlns 
localName - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。 
qName - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。 
attributes - 附加到元素的属性。如果没有属性,则它将是空的 Attributes 对象。 
 --> 

2.创建解析测试类及事件处理的内部类代码如下

package sax.startelement; 
import java.io.File; 
import java.io.FileReader; 
import org.junit.Test; 
import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax.helpers.XMLReaderFactory; 
public class Demo3 { 
 @Test 
 public void test() throws Exception { 
  // 通过XMLReaderFactory创建XMLReader对象 
  XMLReader reader = XMLReaderFactory.createXMLReader(); 
  // 设置事件处理器对象 
  reader.setContentHandler(new MyDefaultHandler()); 
  // 读取要解析的xml文件 
  FileReader fileReader = new FileReader(new File( 
    "src\\sax\\startelement\\web.xml")); 
  // 指定解析的xml文件 
  reader.parse(new InputSource(fileReader)); 
 } 
 // 自定义的解析类,通过此类中的startElement了解uri,localName,qName,Attributes的含义 
 class MyDefaultHandler extends DefaultHandler { 
  @Override 
  public void startElement(String uri, String localName, String qName, 
    Attributes attributes) throws SAXException { 
   super.startElement(uri, localName, qName, attributes); 
   System.out 
     .println("--------------startElement开始执行--------------------------"); 
   System.out.println("uri:::" + uri); 
   System.out.println("localName:::" + localName); 
   System.out.println("qName:::" + qName); 
   for (int i = 0; i < attributes.getLength(); i++) { 
    String value = attributes.getValue(i);// 获取属性的value值 
    System.out.println(attributes.getQName(i) + "-----" + value); 
   } 
   System.out 
     .println("------------------startElement执行完毕---------------------------"); 
  } 
 } 
} 

3.程序运行的结果如下:

通过运行结果,希望你对uri,localName,qName有更加深入的了解.

二.我们通过SAXParserFactory、SAXParser、XMLReader完成,步骤如下

1.使用SAXParserFactory创建SAX解析工厂

SAXParserFactory spf = SAXParserFactory.newInstance();

2.通过SAX解析工厂得到解析器对象

SAXParser sp = spf.newSAXParser();

3.通过解析器对象得到一个XML的读取器

XMLReader xmlReader = sp.getXMLReader();

4.设置读取器的事件处理器

xmlReader.setContentHandler(new BookParserHandler());

5.解析xml文件

xmlReader.parse("book.xml");

说明:如果只是使用SAXParserFactory、SAXParser他们完成只需要如下3步骤

1.获取sax解析器的工厂对象

SAXParserFactory factory = SAXPar
serFactory.newInstance();

2.通过工厂对象 SAXParser创建解析器对象

SAXParser saxParser = factory.newSAXParser();

3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象

saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler());

案例:解析出"作者"元素标签中的文本内容

1.需要解析的sida.xml文件

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE 四大名著[ 
<!ELEMENT 四大名著 (西游记,红楼梦)> 
<!ATTLIST 西游记 id ID #IMPLIED> 
]> 
<四大名著> 
 <西游记 id="x001"> 
  <作者>吴承恩</作者> 
 </西游记> 
 <红楼梦 id="x002"> 
  <作者>曹雪芹</作者> 
 </红楼梦> 
</四大名著> 

2.解析测试类和事件处理器类的实现代码

package sax; 
import java.io.File; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
import org.junit.Test; 
import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.helpers.DefaultHandler; 
public class SaxTest { 
 @Test 
 public void test() throws Exception { 
  // 1.获取sax解析器的工厂对象 
  SAXParserFactory factory = SAXParserFactory.newInstance(); 
  // 2.通过工厂对象 SAXParser创建解析器对象 
  SAXParser saxParser = factory.newSAXParser(); 
  // 3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象 
  saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler()); 
 } 
 // 自己定义的事件处理器 
 class MyDefaultHandler extends DefaultHandler { 
  // 解析标签开始及结束的的标识符 
  boolean isOk = false; 
  @Override 
  public void startElement(String uri, String localName, String qName, 
    Attributes attributes) throws SAXException { 
   super.startElement(uri, localName, qName, attributes); 
   // 当解析作者元素开始的时候,设置isOK为true 
   if ("作者".equals(qName)) { 
    isOk = true; 
   } 
  } 
  @Override 
  public void characters(char[] ch, int start, int length) 
    throws SAXException { 
   // TODO Auto-generated method stub 
   super.characters(ch, start, length); 
   // 当解析的标识符为true时,打印元素的内容 
   if (isOk) { 
    System.out.println(new String(ch, start, length)); 
   } 
  } 
  @Override 
  public void endElement(String uri, String localName, String qName) 
    throws SAXException { 
   super.endElement(uri, localName, qName); 
   // 当解析作者元素的结束的时候,设置isOK为false 
   if ("作者".equals(qName)) { 
    isOk = false; 
   } 
  } 
 } 
} 

3.程序运行结果如下:

相关文章

  • Spring AOP访问目标方法的参数操作示例

    Spring AOP访问目标方法的参数操作示例

    这篇文章主要介绍了Spring AOP访问目标方法的参数操作,结合实例形式详细分析了spring面向切面AOP访问目标方法的参数相关实现步骤与操作注意事项,需要的朋友可以参考下
    2020-01-01
  • SpringBoot处理接口幂等性的两种方法详解

    SpringBoot处理接口幂等性的两种方法详解

    接口幂等性处理算是一个非常常见的需求了,我们在很多项目中其实都会遇到。本文为大家总结了两个处理接口幂等性的两种常见方案,需要的可以参考一下
    2022-06-06
  • SpringBoot使用hutool操作FTP的详细过程

    SpringBoot使用hutool操作FTP的详细过程

    在使用SpringBoot结合hutool操作FTP时,遇到防火墙导致上传文件大小为0kb的问题,通过设置FTP为被动模式解决,本文详细解析了FTP的主动模式和被动模式的工作原理、安全性及适用场景,帮助理解FTP的连接方式和解决网络限制问题
    2024-09-09
  • SpringCloud微服务多应用脚手架的搭建与部署方式

    SpringCloud微服务多应用脚手架的搭建与部署方式

    这篇文章主要介绍了SpringCloud微服务多应用脚手架的搭建与部署方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • SpringBoot实现加载yml文件中字典数据

    SpringBoot实现加载yml文件中字典数据

    这篇文章主要为大家详细介绍了SpringBoot如何实现加载yml文件中字典数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-04-04
  • Spring如何基于Proxy及cglib实现动态代理

    Spring如何基于Proxy及cglib实现动态代理

    这篇文章主要介绍了Spring如何基于Proxy及cglib实现动态代理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 基于SpringMVC对接前端参数注解

    基于SpringMVC对接前端参数注解

    这篇文章主要介绍了基于SpringMVC对接前端参数注解的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • java多线程读取多个文件的方法

    java多线程读取多个文件的方法

    这篇文章主要为大家详细介绍了java多线程读取多个文件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • java中的Reference和引用类型实例精讲

    java中的Reference和引用类型实例精讲

    这篇文章主要为大家介绍了java中的Reference和引用类型示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Springboot详解整合SpringSecurity实现全过程

    Springboot详解整合SpringSecurity实现全过程

    Spring Security基于Spring开发,项目中如果使用Springboot作为基础,配合Spring Security做权限更加方便,而Shiro需要和Spring进行整合开发。因此作为spring全家桶中的Spring Security在java领域很常用
    2022-07-07

最新评论