部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

Java学习笔记--xml构造与解析之Sax的使用

汇总:xml的构造与解析 http://www.cnblogs.com/gnivor/p/4624058.html 

参考资料:http://www.iteye.com/topic/763895

利用SAX存储XML(一般不这么用)

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

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

import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

public class MySax {    
    
    public static void main(String[] args) throws FileNotFoundException, TransformerConfigurationException, SAXException{  
        MySax mysax = new MySax();
        mysax.generate();
    }  
    
    
    //生成xml文档的函数
    public void generate() throws FileNotFoundException, TransformerConfigurationException, SAXException{        
        Result resultXml = new StreamResult(new FileOutputStream("c:\\person.xml")); //输出到person.xml
        
        SAXTransformerFactory sff = (SAXTransformerFactory)SAXTransformerFactory.newInstance();  
        TransformerHandler th = sff.newTransformerHandler();  
        th.setResult(resultXml);  
          
        Transformer transformer = th.getTransformer();  
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //编码格式是UTF-8  
        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //换行  
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");// 是否忽略xml声明
        
        AttributesImpl attr = new AttributesImpl();
        
        th.startDocument(); //开始xml文档         
        
        th.startElement("", "", "person", attr); //定义person节点  
        
        
        th.startElement("", "", "name", attr); //定义name节点  
        th.characters("张三".toCharArray(), 0, "张三".length());  
        th.endElement("", "", "name"); //结束name节点     
        
        th.startElement("", "", "age", attr); //定义age节点  
        th.characters("29".toCharArray(), 0, "29".length());  
        th.endElement("", "", "age"); //结束age节点       
        
        th.startElement("", "", "gender", attr); //定义gender节点  
        th.characters("男".toCharArray(), 0, "男".length());  
        th.endElement("", "", "gender"); //结束gender节点         
        
        th.endElement("", "", "person"); //结束person节点  
        
        th.endDocument(); //结束xml文档          
    }
}
View Code

 

利用SAX对XML进行解析

要解析的文件 

<?xml version="1.0" encoding="UTF-8"?>  
<books>  
    <book id="12">  
        <name>thinking in java</name>  
        <price>85.5</price>  
    </book>  
    <book id="15">  
        <name>Spring in Action</name>  
        <price>39.0</price>  
    </book>  
</books>  

解析方法

xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析。
当读入<?xml.....>时,会调用startDocument()方法,
当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法。
注意:上面方法第二个参数就是节点的名称.由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用。第4个参数是这个节点的属性。
我们不需要<books>这个节点,所以从<book>这个节点开始,也就是图中1的位置。
当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到,
然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。具体见代码。

Book

class Book {  
    private int id;  
    private String name;  
    private float price;  
      
    public void setId(int id) {  
        this.id = id;  
    }        
    public void setName(String name) {  
        this.name = name;  
    }        
    public void setPrice(float price) {  
        this.price = price;  
    }  
    @Override  
    public String toString(){  
        return "id:"+ this.id+", 书名:"+this.name+", 价格:"+this.price;  
    }  
}  


SaxParseService

class SaxParseService extends DefaultHandler{  
    private List<Book> books = null;  
    private Book book = null;  
    private String preTag = null;//作用是记录解析时的上一个节点名称  
      
    public List<Book> getBooks(InputStream xmlStream) throws Exception{  
        SAXParserFactory factory = SAXParserFactory.newInstance();  
        SAXParser parser = factory.newSAXParser();  
        SaxParseService handler = new SaxParseService();  
        parser.parse(xmlStream, handler); //对文件流进行解析  
        return handler.books; //返回结果  
    }    
    
    //第1个分析点事件方法。在该方法中创建了用于保存 转换结果的List<Book>对象
    @Override  
    public void startDocument() throws SAXException {  
        books = new ArrayList<Book>();  
    }  
  
    //第2个分析点事件方法。SAX引擎分析到每一个<book>元素时,在该方法中都会创建一个Book对象
    @Override  
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {  
        if("book".equals(qName)){  
            book = new Book();  
            book.setId(Integer.parseInt(attributes.getValue(0)));  
        }  
        preTag = qName;//将正在解析的节点名称赋给preTag  
    }  

    //第3个分析点事件方法。当SAX引擎每分析完一个XML元素之后,会将当前book加入到Books列表之中
    @Override  
    public void endElement(String uri, String localName, String qName)  
            throws SAXException {  
        if("book".equals(qName)){  
            books.add(book);  
            book = null;  
        }  
        preTag = null;
        
        /* 当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法
         * ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图 
         * 中标记4的位置时,会执行characters(char[] ch, int start, int length)这个方法,
         * 而characters(....)方法判断preTag!=null,会执行if判断的代码,
         * 这样就会把空值赋值给book,这不是我们想要的。
         * */  
    }  
    
    //第4个分析点事件方法。分析每一个book元素,并将book元素的属性保存在Book对象之中
    @Override  
    public void characters(char[] ch, int start, int length) throws SAXException {  
        if(preTag!=null){  
            String content = new String(ch,start,length);  
            if("name".equals(preTag)){  
                book.setName(content);  
            }else if("price".equals(preTag)){  
                book.setPrice(Float.parseFloat(content));  
            }  
        }  
    }  
}  


测试类

public class BookSax {    
    public static void main(String[] args) throws Throwable{  
        BookSax booksax = new BookSax();
        booksax.testSAX();
    }    
    public void testSAX() throws Throwable{  
        SaxParseService sax = new SaxParseService();  
        File file = new File("F:\\测试TXT\\book.xml");
        FileInputStream input = new FileInputStream(file); 
        
        List<Book> books = sax.getBooks(input);  
        for(Book book : books){  
            System.out.println(book.toString());  
        }  
    }  
}

 

运行结果:

id:12, 书名:thinking in java, 价格:85.5
id:15, 书名:Spring in Action, 价格:39.0

posted @ 2015-11-07 16:15  流了个火  阅读(327)  评论(0编辑  收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats