SAX是基于事件驱动的方式,一条一条的读写文件,从而触发相关方法。由于它不像DOM方式一样,将整个文档加载后再进行解析,所以对内存的耗费较少,生成和解析的速度非常快,适用于只需要处理XML中的数据时,但不适用同时访问同一个XML中的不同数据。
一、SAX解析XML文件 1.1 解析准备1、获取SAXParserFactory的实例factory;
2、通过factory获取SAXParser的实例parser;
3、创建一个SAXParserHandler对象handler,通过parser的parse方法进行解析。
1.2 解析过程
1、创建SAXParserHandler类,并继承DefaultHandler类;
2、重写startDocument方法,标识解析开始;
3、重写startElement方法,遍历文件的开始标签;
4、若需要获取节点值,则要重写characters(char ch[],int start,int length)方法;
5、重写endElement()方法结束遍历标签;
6、重写endDocument()方法结束解析文档。
1.3 将解析内容存储到对象
1、新建对象类,设置好属性和setter/getter方法;
2、在解析的方法里,利用setter方法将内容传入对象。
public class Book {
private String id;
private String name;
private String author;
private String year;
private String price;
private String language;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
public ArrayList<Book> parseXML() throws Exception, SAXException {
// 获取SAXParserFactory的实例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 获取SAXParser实例parser
SAXParser parser = factory.newSAXParser();
// 创建一个SAXParserHandler对象
SAXParserHandler handler = new SAXParserHandler();
parser.parse("books.xml", handler); // 开始进行解析
System.out.println("书的数目:" + handler.getBooklist().size());
for (Book book : handler.getBooklist()) {
System.out.println(book.getId() + " " + book.getAuthor() + " " + book.getName() + " " + book.getPrice()
+ " " + book.getYear() + " " + book.getLanguage());
System.out.println("------------------");
}
return handler.getBooklist();
}
public class SAXParserHandler extends DefaultHandler {
int bookIndex; //定义全局变量,用于给书计数
String value = null;
Book book = null;
private ArrayList<Book> booklist = new ArrayList<Book>();
public ArrayList<Book> getBooklist() {
return booklist;
}
public void setBooklist(ArrayList<Book> booklist) {
this.booklist = booklist;
}
//以下方法均通过Alt+/进行重载,分别用来遍历文件的开始标签和结束标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
//解析book标签
if(qName.equals("book")){
bookIndex++;
book = new Book();
System.out.println("=====开始遍历第"+bookIndex+"本书的内容=====");
//若已知book下属性的名称为id,获取属性值的方法如下
//System.out.println("book的属性值是:"+attributes.getValue("id"));
//若不知book下的属性名称个数和值,则使用循环进行遍历
for(int i=0;i<attributes.getLength();i++){
System.out.print("属性名是:"+attributes.getQName(i));
System.out.println("--->属性值是:"+attributes.getValue(i));
if("id".equals(attributes.getQName(i))){
book.setId(attributes.getValue(i));
}
}
}else if(!qName.equals("book")&&!qName.equals("bookstore")){
System.out.print("节点名:"+qName+"---->");
}
}
@Override
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;
System.out.println("=====结束遍历第"+bookIndex+"本书的内容=====");
}else if(qName.equals("name")){
book.setName(value);
}else if(qName.equals("author")){
book.setAuthor(value);
}else if(qName.equals("year")){
book.setYear(value);
}else if(qName.equals("price")){
book.setPrice(value);
}else if(qName.equals("language")){
book.setLanguage(value);
}
}
//以下两个方法用来标识解析开始和结束
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("begin!");
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("end!");
}
//获取节点值,ch字符数组是整个xml文本的内容,start是开始节点的位置,length为长度
@Override
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);
}
}
}
二、SAX生成XML文件
2.1 XML文档生成
1、创建SAXTransformerFactory对象tff;
2、通过tff创建一个TransformerHandler对象handler;
3、通过Handler创建Transformer对象tr;
4、利用tr可对XML文档格式进行设置;
5、创建一个result对象,与handler相关联。
2.2 XML文档内容的生成
public void createXML() throws SAXException, Exception{
ArrayList<Book> bookList = parseXML();
//生成XML文件,1、创建一个SAXTransformerFactory的对象
SAXTransformerFactory tff = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
//2、通过SAXtransformerFactory对象创建一个TransformerHandler的对象
TransformerHandler handler = tff.newTransformerHandler();
//3、通过Handler对象创建一个Transformer对象
Transformer tr = handler.getTransformer();
//4、通过Transformer对象对生成的XML文件进行设置
tr.setOutputProperty(OutputKeys.ENCODING, "utf-8");
tr.setOutputProperty(OutputKeys.INDENT, "yes");
//5、创建一个result对象,并与Handler关联
File file = new File("books2.xml");
if(!file.exists()){
file.createNewFile();
}
Result result = new StreamResult(new FileOutputStream(file));
handler.setResult(result);
//利用Handler对象进行XML文件内容的编写
//打开document
handler.startDocument();
AttributesImpl atts = new AttributesImpl();
handler.startElement("", "", "bookstore", atts);
for(Book book:bookList){
atts.clear();
atts.addAttribute("", "", "id", "", book.getId());
handler.startElement("","","book",atts);
//创建name子节点
if(book.getName()!=null && !book.getName().trim().equals("")){
atts.clear();
handler.startElement("", "", "name", atts);
handler.characters(book.getName().toCharArray(), 0, book.getName().length());
handler.endElement("", "", "name");
}
//创建author子节点
if(book.getAuthor()!=null && !book.getAuthor().trim().equals("")){
atts.clear();
handler.startElement("", "", "author", atts);
handler.characters(book.getAuthor().toCharArray(), 0, book.getAuthor().length());
handler.endElement("", "", "author");
}
//创建year子节点
if(book.getYear()!=null && !book.getYear().trim().equals("")){
atts.clear();
handler.startElement("", "", "year", atts);
handler.characters(book.getYear().toCharArray(), 0, book.getYear().length());
handler.endElement("", "", "year");
}
//创建price子节点
if(book.getPrice()!=null && !book.getPrice().trim().equals("")){
atts.clear();
handler.startElement("", "", "price", atts);
handler.characters(book.getPrice().toCharArray(), 0, book.getPrice().length());
handler.endElement("", "", "price");
}
//创建language子节点
if(book.getLanguage()!=null && !book.getLanguage().trim().equals("")){
handler.startElement("", "", "language", atts);
handler.characters(book.getLanguage().toCharArray(), 0, book.getLanguage().length());
handler.endElement("", "", "language");
}
handler.endElement("", "", "book");
}
handler.endElement("", "", "bookstore");
//关闭document
handler.endDocument();
}