加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

【Java编程】SAX XML Parser解析、生成XML文件

发布时间:2020-12-16 05:54:53 所属栏目:百科 来源:网络整理
导读:1、优缺点 优点: SAX 从根本上解决了 DOM 在解析 XML 文档时产生的占用大量资源的问题。其实现是 通过类似于流解析的技术,通读整个 XML 文档树,通过事件处理器来响应程序员对于 XML 数据解析的需求 。由于其不需要将整个 XML 文档读入内存当中,它对系统

1、优缺点

优点:

SAX 从根本上解决了 DOM 在解析 XML 文档时产生的占用大量资源的问题。其实现是通过类似于流解析的技术,通读整个 XML 文档树,通过事件处理器来响应程序员对于 XML 数据解析的需求。由于其不需要将整个 XML 文档读入内存当中,它对系统资源的节省是十分显而易见的,它在一些需要处理大型 XML 文档以及性能要求较高的场合有起了十分重要的作用。支持 XPath 查询的 SAX 使得开发人员更加灵活,处理起 XML 来更加的得心应手。

缺点:

但是同时,其仍然有一些不足之处也困扰广大的开发人员:首先是它十分复杂的 API 接口令人望而生畏,其次由于其是属于类似流解析的文件扫描方式,因此不支持应用程序对于 XML 树内容结构等的修改,可能会有不便之处

适用范围:

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

2、触发器工作流程

在Sax的解析过程中,读取到文档开头、结尾,元素的开头和结尾都会触发一些回调方法,你可以在这些回调方法中进行相应事件处理这四个方法是:startDocument() 、endDocument()、 startElement()、endElement。此外,我们还需要characters()方法来仔细处理元素内包含的内容将这些回调方法集合起来,便形成了一个触发器类DefaultHandler。一般从Main方法中读取文档,却在触发器中处理文档,这就是所谓的事件驱动解析方法


如上图,在触发器中,首先开始读取文档,然后开始逐个解析元素,每个元素中的内容会返回到characters()方法接着结束元素读取,所有元素读取完后,结束文档解析

DefaultHandler类:


3、SAX解析XML文件

使用XMLReader解析

// 1.新建一个工厂类SAXParserFactory

SAXParserFactory factory =SAXParserFactory.newInstance();

// 2.让工厂类产生一个SAX的解析类SAXParser

SAXParser parser = factory.newSAXParser();

// 3.从SAXPsrser中得到一个XMLReader实例

XMLReader reader = parser.getXMLReader();

// 4.得到内容处理器

SaxHandler saxHandler = new SaxHandler();

// 5.把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler

reader.setContentHandler(saxHandler);

// 6.将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始

reader.parse(newInputSource(new FileInputStream("src/com/andieguo/saxparserdemo/books.xml")));

使用SAXParser解析

// 1.创建解析工厂

SAXParserFactory saxParserFactory =SAXParserFactory.newInstance();// 获取单例

// 2.得到解析器

SAXParser saxParser = saxParserFactory.newSAXParser();

// 3.得到内容处理器

SaxHandler saxHandler = new SaxHandler();

// 4.解析器绑定内容处理器,并解析xml文件

saxParser.parse(new File("src/com/andieguo/saxparserdemo/books.xml"),saxHandler);

实战

1) books.xml(同上一篇【Java编程】DOM XML Parser解析、遍历、创建XML)

2) Book.java(同上一篇【Java编程】DOM XML Parser解析、遍历、创建XML)

3) SaxHandler.java:触发器类,里面有各种回调方法,当解析XML文档时触发了事件回调该类里相应的方法。

package com.andieguo.saxparserdemo;

import java.util.ArrayList;
import java.util.List;

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

public class SaxHandler extends DefaultHandler {

	private List<Book> bookList = null;
	private Book book = null;
	private boolean bTitle = false;
	private boolean bAuthor = false;
	private boolean bYear = false;
	private boolean bPrice = false;

	public List<Book> getBookList() {
		return bookList;
	}

	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
	}

	@Override
	public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
		if (qName.equalsIgnoreCase("book")) {
			String category = attributes.getValue("category");// 获取book元素的Attributes值
			book = new Book();
			book.setCategory(category);
			if (bookList == null) {
				bookList = new ArrayList<Book>();
			}
		} else if (qName.equalsIgnoreCase("title")) {
			String titleLang = attributes.getValue("lang");// 获取title元素的Attributes值
			book.setTitleLang(titleLang);
			bTitle = true;
		} else if (qName.equalsIgnoreCase("author")) {
			bAuthor = true;
		} else if (qName.equalsIgnoreCase("year")) {
			bYear = true;
		} else if (qName.equalsIgnoreCase("price")) {
			bPrice = true;
		}
	}

	@Override
	public void endElement(String uri,String qName) throws SAXException {
		if (qName.equalsIgnoreCase("book")) {
			bookList.add(book);
		}
	}

	@Override
	public void characters(char[] ch,int start,int length) throws SAXException {
		if (bTitle) {
			book.setTitle(new String(ch,start,length));
			bTitle = false;// 解析完后,必须关闭掉;因为解析到下一个元素Author时characters还会被执行,如果不关闭掉会首先执行进来。
		} else if (bAuthor) {
			if (book.getAuthor() == null) {
				book.setAuthor(new String(ch,length));
			} else {
				book.setAuthor(book.getAuthor() + "/" + new String(ch,length));// 解决有多个作者的问题
			}
			bAuthor = false;
		} else if (bYear) {
			book.setYear(Integer.parseInt(new String(ch,length)));
			bYear = false;
		} else if (bPrice) {
			book.setPrice(Double.parseDouble(new String(ch,length)));
			bPrice = false;
		}
	}

	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
	}

}

4) XMLParserSAX.java:解析XML文件并写入到List<Book>集合,这样做的好处是实现了将任意平台都能处理的XML数据转化为了Java能处理的对象,方便在Java或Android开发中的后续数据处理,比如说:在Android中,从服务器上获取到XML文件,通过该方法解析数据并存入到对象,再将该对象绑定到适配器用于Listview的显示,一种很常用的开发需求。

package com.andieguo.saxparserdemo;

import java.io.File;
import java.io.FileInputStream;
import java.util.List;

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

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class XMLParserSAX {

	public static void main(String[] args) {
		//List<Book> books = xmlReader(new File("src/com/andieguo/saxparserdemo/books.xml"));
		List<Book> books = saxParser(new File("src/com/andieguo/saxparserdemo/books.xml"));
		for (Book book : books) {
			System.out.println(book.toString());
		}
	}
	//使用SAXParser来解析 
	public static List<Book> saxParser(File file) {
		try {
			// 1.创建解析工厂
			SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();// 获取单例
			// 2.得到解析器
			SAXParser saxParser = saxParserFactory.newSAXParser();
			// 3.得到内容处理器
			SaxHandler saxHandler = new SaxHandler();
			// 4.解析器绑定内容处理器,并解析xml文件
			saxParser.parse(file,saxHandler);
			List<Book> books = saxHandler.getBookList();
			return books;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	//使用XMLReader 来解析 
	public static List<Book> xmlReader(File file) {
		try {
			// 1.新建一个工厂类SAXParserFactory
			SAXParserFactory factory = SAXParserFactory.newInstance();
			// 2.让工厂类产生一个SAX的解析类SAXParser
			SAXParser parser = factory.newSAXParser();
			// 3.从SAXPsrser中得到一个XMLReader实例
			XMLReader reader = parser.getXMLReader();
			// 4.得到内容处理器
			SaxHandler saxHandler = new SaxHandler();
			// 5.把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler
			reader.setContentHandler(saxHandler);
			// 6.将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始
			reader.parse(new InputSource(new FileInputStream(file)));
			List<Book> books = saxHandler.getBookList();
			return books;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

5) 执行该类的main方法,console效果如下:

4、SAX生成XML文件

1)SAXTransformerFactory类

此类扩展了 TransformerFactory 以提供特定于 SAX的工厂方法。它提供两种类型的 ContentHandler,一种用于创建 Transformer,另一种用于创建 Templates 对象。

如果应用程序希望设置转换期间所使用的 XMLReader 的ErrorHandler 或 EntityResolver,那么它应使用 URIResolver 来返回提供了(通过 getXMLReader)对 XMLReader 引用的 SAXSource。


2)TransformerHandler类

侦听 SAX ContentHandler 解析事件,并将它们转换为 Result 的 TransformerHandler

实战

1)CreateXMLFile.java:将对象里的数据填充到构建的XML文件中。
package com.andieguo.saxparserdemo;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.helpers.AttributesImpl;

public class CreateXMLFile {


	public static void main(String[] args) {
		List<Book> books = XMLParserSAX.xmlReader(new File("src/com/andieguo/saxparserdemo/books.xml"));
		createXML(books);
		
	}

	public static void createXML(List<Book> books) {

		try {
			// 创建工厂
			SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
			TransformerHandler handler = factory.newTransformerHandler();
			Transformer info = handler.getTransformer();
			// 是否自动添加额外的空白
			info.setOutputProperty(OutputKeys.INDENT,"yes");
			// 设置字符编码
			info.setOutputProperty(OutputKeys.ENCODING,"utf-8");
			info.setOutputProperty(OutputKeys.VERSION,"1.0");
			// 保存创建的saxbooks.xml
			StreamResult result = new StreamResult(new FileOutputStream(new File("src/com/andieguo/saxparserdemo/saxbooks.xml")));
			handler.setResult(result);
			// 开始xml
			handler.startDocument();
			AttributesImpl impl = new AttributesImpl();
			impl.clear();
			handler.startElement("","","bookstore",impl);
			for(int i=0;i<books.size();i++){
				Book book = books.get(i);
				//生成<book category="xx">
				impl.clear(); //清空属性
	            impl.addAttribute("","category",book.getCategory());//为book元素添加category属性
	            handler.startElement("","book",impl); 
	            //生成<title lang="xx">xx</title>元素
	            impl.addAttribute("","lang",book.getTitleLang());//为title元素添加lang属性
	            handler.startElement("","title",impl); 
	            String title = book.getTitle();
	            handler.characters(title.toCharArray(),title.length()); //为title元素添加文本
	            handler.endElement("","title"); 
	            //生成<author>xx</author>元素
	            String[] author = book.getAuthor().split("/");
	            for(int j=0;j<author.length;j++){
	            	impl.clear(); 
	            	handler.startElement("","author",impl); 
	            	handler.characters(author[j].toCharArray(),author[j].length()); 
	 	            handler.endElement("","author"); 
	            }
	            //生成<year>xx</year>元素
	            impl.clear(); 
	            handler.startElement("","year",impl); 
	            String year = book.getYear().toString();
	            handler.characters(year.toCharArray(),year.length()); 
	            handler.endElement("","year"); 
	            //生成<price>xx</price>元素
	            impl.clear(); 
	            handler.startElement("","price",impl); 
	            String price = book.getPrice().toString();
	            handler.characters(price.toCharArray(),price.length()); 
	            handler.endElement("","price"); 
	            //生成</book>
	            handler.endElement("","book");
			}
			//生成</bookstore>
			handler.endElement("","bookstore");
			handler.endDocument();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
2)生成的文件saxbooks.xml

5、参考:

Java SAX Parser Example Tutorial to parseXML to List of Objects

http://www.journaldev.com/1198/java-sax-parser-example-tutorial-to-parse-xml-to-list-of-objects

Java 处理 XML 的三种主流技术及介绍

http://www.ibm.com/developerworks/cn/xml/dm-1208gub/

XML之SAX方式 解析和生成XML文件

http://www.52php.cn/article/p-ckzzmezm-ca.html

6、小结

花了一天的时间,将常用的解析XML文件的两种方式总结了下,参考了不少blog和资料,总算对DOM XML Parser 和 SAX XML Parser两种解析方式有了个清晰的认识。再次明白懂技术容易,掌握技术难,将技术明明白白写出来难上加难,写blog不仅仅是个记录的过程,更是一种思路的理清过程,因为你要讲的让人听的懂。如果技术是硬实力的话,写的一手好blog是一种软实力。

转载请注明出处:http://www.52php.cn/article/p-xbotzfgt-xp.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读