zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    01数据结构——绪论
    07机器学习实战k-means
    OpenJudge 2756 二叉树
    Poj/OpenJudge 1094 Sorting It All Out
    OpenJudge 2811 熄灯问题 / Poj 1222 EXTENDED LIGHTS OUT
    OpenJudge/Poj 1083 Moving Tables
    OpenJudge 2810(1543) 完美立方 / Poj 1543 Perfect Cubes
    Poj/OpenJudge 1042 Gone Fishing
    Poj 1013 Counterfeit Dollar / OpenJudge 1013(2692) 假币问题
    Poj 1017 / OpenJudge 1017 Packets/装箱问题
  • 原文地址:https://www.cnblogs.com/gnivor/p/4945577.html
Copyright © 2011-2022 走看看