SAX解析xml全解

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <books index="1">aa
 3     <book index="2" id="12" color="red" >xx
 4         <name  index="3" color="green" type="嘿嘿">thinking in java</name>
 5         <price index="4">85.5</price><price index="4">86.5</price>
 6     </book>nn
 7     <book index="5" id="15" color="blue" >
 8         <name index="6" value="xx" type="哈哈" ><![CDATA[&haha<>]]> Spring in Action</name>
 9         <price index="7">39.0</price>
10     </book>mm
11 </books>
Book.xml

下面这个是解析类,需要导入jar包xercesImpl.jar

首先要获得解析器,然后要将解析器注册到处理器

  1 package com.Sax.demo;
  2 
  3 import org.xml.sax.Attributes;
  4 import org.xml.sax.Locator;
  5 import org.xml.sax.SAXException;
  6 import org.xml.sax.XMLReader;
  7 import org.xml.sax.ext.LexicalHandler;
  8 import org.xml.sax.helpers.DefaultHandler;
  9 import org.xml.sax.helpers.XMLReaderFactory;
 10 /**
 11  * http://docs.oracle.com/javaee/1.4/tutorial/doc/JAXPIntro4.html
 12  * @author ibn
 13  * LexicalHandler是拓展接口 必须通过XMLReader属性进行注册
 14  * 通过属性注册,将拓展接口传递给处理器
 15  * reader.setPropeerty("属性名",this)  这个属性名是固定的
 16  * 而在DefalutHandler里面,可以直接setContentHandler进行注册
 17  *
 18  */
 19 public class BookReader extends DefaultHandler implements LexicalHandler{
 20     private boolean isColor;
 21     private String bookType;
 22     private StringBuffer bookColor=new StringBuffer();
 23     private Locator bookLocator;
 24     public static void main(String[]args)throws Exception{
 25         StringBuffer sb=new StringBuffer();
 26         sb.append(false);
 27         sb.append(true);
 28         System.out.println("sb"+sb);
 29         System.out.println("Running Start....");
 30         BookReader tr=new BookReader();
 31         tr.read("src/Book.xml");
 32     }
 33     /**
 34      * 利用XMLReaderFactory创建一个XMLReader对象
 35      * 将已注册的解析器名传给XMLReaderFactory 得到XMLReader
 36      * 解析前通知XMLreader接收与解析xml文档内容有关的事件处理器
 37      * 然后给需要解析的文档名传递给解析器
 38      * 解析器不能保存前一事件的数据
 39      * 这个文档路径默认相对路径是在功能目录下
 40      * 解析xml开始时机会将startDocument事件传给事件解析器 即这个TrainReader,执行startDocument()函数
 41      * @param fileName
 42      * @throws Exception
 43      */
 44     public void read(String fileName) throws Exception{
 45         //驱动
 46         XMLReader reader=XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
 47         reader.setContentHandler(this);
 48         reader.setErrorHandler(this);//将验证属性呢设置为true
 49         /*
 50          *dafaultHandler并没有为LexicalHandler提供了实现程序
 51          *所以使用这些拓展接口的时候需要通过属性注册
 52          */
 53         reader.setProperty("http://xml.org/sax/properties/lexical-handler", this);
 54         //reader.setFeature(name, value);
 55         reader.parse(fileName);
 56     }
 57     public void startDocument(){
 58         System.out.println("Start of the train...");
 59     }
 60     public void endDocument(){
 61         System.out.println("End of the trail...");
 62     }
 63     /**
 64      * 处理元素和属性
 65      * 名称空间URI http://example.com
 66      * 局部名(localname)  myElement
 67      * 限定名(qname) myPrefix:myElement
 68      * <myPrefix:myElement xmlns:myPrefix="http://example.com">
 69      * 如果uri不为空 利用uri+localname而不是利用qname来确定元素 具体原因:不同文档同一uri的前缀可能不同
 70      * Attributes接口 可以访问每个元素的属性和初始值
 71      */
 72     public void startElement(String uri,String localName,String qName,Attributes atts){
 73         System.err.println("TestA");
 74         System.err.println(atts.getValue("index"));
 75         System.out.println("index:"+atts.getIndex(qName)+" qName:"+qName);
 76 //        if("book".equals(localName)){
 77 //            if(atts!=null){
 78 //                System.out.println("Book:"+atts.getValue("id"));
 79 //                String color=atts.getValue("color");
 80 //                System.out.println("color:"+color);
 81 //                if(color.equals("red")){
 82 //                    System.out.println("红书");
 83 //                }
 84 //            }
 85 //        }else 
 86             if("name".equals(localName)){
 87             if(atts!=null){
 88                 isColor=true;
 89                 bookType=atts.getValue("type");
 90                 System.out.println("name:"+atts.getValue("value"));
 91                 String color=atts.getValue("color");
 92                 System.out.println("color:"+color);
 93             }
 94         }else{
 95             isColor=false;
 96         }
 97     }
 98     /**
 99      * 元素结束
100      */
101     public void endElement(String uri,String localName,String qName){
102         System.err.println("testC:"+localName);
103         //if(isColor){
104             //    System.out.println("The color of name:"+bookColor+" type:"+bookType);
105         //}
106     }
107     /**
108      * 处理元素中间的文本内容
109      * 该方法在元素由文本内容会调用一次
110      * 在每次换行也会调用一次
111      * ch处理的文本字符串
112      * start 开始的位置index
113      * len 文本字符串长度
114      */
115     public void characters(char[]ch,int start,int len)throws SAXException{
116         System.err.println("testB:"+new StringBuffer().append(ch, start, len));
117         if(isColor){
118             bookColor.append(ch, start, len);
119             System.out.println("start:"+ch[0]);
120             System.out.println("len:"+len);
121         }
122     }
123     /**
124      * 在元素开始解析之前,将该接口传递给了本程序
125      * 解析器把Locator接口传递给程序
126      * 在出错位置可以利用如下的两个方法定位出错的行号和列号
127      * 在endElement里面将异常抛出,异常信息利用Locator接口得到行号和列号
128      *
129      */
130     public void setDocumentLocator(Locator locator){//ContenHandler
131         System.out.println("Locator接口");
132         locator.getLineNumber();//当前事件的行号
133         locator.getColumnNumber();//当前事件的列号
134         bookLocator=locator;
135     }
136     public void comment(char[] ch, int start, int length) throws SAXException {
137         // TODO Auto-generated method stub
138         
139     }
140     public void endCDATA() throws SAXException {
141         // TODO Auto-generated method stub
142         
143     }
144     public void endDTD() throws SAXException {
145         // TODO Auto-generated method stub
146         
147     }
148     public void endEntity(String name) throws SAXException {
149         // TODO Auto-generated method stub
150         
151     }
152     /**
153      * 上面已经通过setProperty进行了属性注册
154      * 当解析器访问CDATA段的开始标签就会将里面的内容传递给应用程序
155      */
156     public void startCDATA() throws SAXException {
157         System.out.println("注册cddata");
158         
159     }
160     public void startDTD(String name, String publicId, String systemId)
161             throws SAXException {
162         // TODO Auto-generated method stub
163         
164     }
165     public void startEntity(String name) throws SAXException {
166         // TODO Auto-generated method stub
167         
168     }
169     
170     
171 }
BookReader.xml

我打印了一下这个index,发现顺序是1,2,3,4,5,6,7所以这个解析element的顺序是从上往下进行的。

我们写的类继承了DefaultHandler,这个处理器本身已经实现了四个接口

我们要先获得一个解析器

我们需要做的就是将这个解析器给他注册到我们的处理器上,然后在处理器的各个相应方法里面处理xml文档

如果我们需要拓展接口时,就需要通过setProperty("uri形式的固定属性",处理器);将解析器注册到处理器

基本的步骤是:

首先startDocument开始处理xml,setDocumentLocator(Lacator)将这个接口传递给处理器(此接口能获得当前处理的行号和列号),

startElement(...)解析每个元素触发该方法(获得其namespace的uri和局部名和限定名及元素属性),characters(...)当元素之间有文本内容,当遇到</...>触发endElement方法

这个character()方法在每次换行会调用一次在解析每个元素内容时也会调用一次!

因为解析器会将开始标签和结束标签之间的字符当做一个文本块来处理,因此需要多次characters事件才能生成一个文本块

现在有个问题在整个Books里面 如果在多个地方有文本块,怎么将这些文本块合在一起啊?

原文地址:https://www.cnblogs.com/javahuang/p/3108273.html