zoukankan      html  css  js  c++  java
  • 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里面 如果在多个地方有文本块,怎么将这些文本块合在一起啊?

  • 相关阅读:
    0149-函数可以做参数.abb
    0139-文件操作之二进制方式打开模式(一).abb
    0138-文件操作之基本打开模式.abb
    0130-实例之python实现随机验证码.abb
    0127-python内置函数(一).abb
    0126-lambda表达式.abb
    0113-全局变量和局部变量.abb
    函数的动态参数
    0103-深浅拷贝.abb
    0102-不同数据类型在内存中的存址方式
  • 原文地址:https://www.cnblogs.com/javahuang/p/3108273.html
Copyright © 2011-2022 走看看