`
yunchow
  • 浏览: 317693 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

SAX 解析 XML 实例

阅读更多
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<class>
  <student>
   <name>Kyte</name>
    <gender>male</gender>
		<job>engineer</job>
	</student>
	<student>
		<name>Charry</name>
		<gender>female</gender>
		<job>manager</job>
	</student>
</class>


JavaBean类:

package com.mypack.sax;

import java.io.Serializable;

public class Student implements Serializable
{
    
    private static final long serialVersionUID = -5211833327339857099L;
    
    private String name;
    
    private String gender;
    
    private String job;
    
    public String getName()
    {
        return name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
    
    public String getGender()
    {
        return gender;
    }
    
    public void setGender(String gender)
    {
        this.gender = gender;
    }
    
    public String getJob()
    {
        return job;
    }
    
    public void setJob(String job)
    {
        this.job = job;
    }
    
    @Override
    public String toString()
    {
        return "{name = " + this.name + ", gender = " + this.gender + ", job = " + this.job + "}";
    }
    
}




SAX 解析类:
package com.mypack.sax;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * @date 2010-08-21
 */
public class SaxParser
{
    
    /**
     * 
     */
    public static void main(String[] args) throws SAXException, IOException
    {
        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
        ClassesHandler handler = new ClassesHandler();
        
        xmlReader.setContentHandler(handler);
        xmlReader.parse("file:c:/t.xml");
        
        System.out.println(handler.stus);
        
    }
    
    private static class ClassesHandler extends DefaultHandler
    {

        private List<Student> stus;
        private Student stu;
        private Stack<String> ctx;
        private StringBuilder sb;
        
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException
        {
            if (ctx != null)
            {
                String tmp = new String(ch, start, length);
                tmp = tmp.replaceAll("\\n|\\t+|\\s+", "");
                this.sb.append(tmp);
            }
        }

        @Override
        public void endElement(String uri, String localName, String name)
                throws SAXException
        {
            if (this.ctx.isEmpty())
            {
                return;
            }
            
            String tmp = this.ctx.pop();
            
            if ("student".equals(tmp))
            {
                stus.add(stu);
                stu = new Student();
            }
            else
            {
                try
                {
                    PropertyDescriptor pd = new PropertyDescriptor(tmp, Student.class);
                    pd.getWriteMethod().invoke(stu, sb.toString());
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
            
            this.sb = new StringBuilder();
        }

        @Override
        public void startDocument() throws SAXException
        {
            this.stus = new ArrayList<Student>();
            this.stu = new Student();
            this.ctx = new Stack<String>();
            this.sb = new StringBuilder();
        }

        @Override
        public void startElement(String uri, String localName, String name,
                Attributes attributes) throws SAXException
        {
            if ("student".equals(name) || !this.ctx.isEmpty())
            {
                ctx.push(name);
            }
        }
        
    }
    
}




处理器范型实现

/*
 * SAX Generic Handler
 * Version: 1.0
 * Date   : 2010-08-24
 */
package com.mypack.sax;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * SAX通用处理器,用于处理简单XML结构,范形实现
 * @date 2010-08-24
 */
public class BeanHandlerForSAX<T> extends DefaultHandler
{
    /** 目标集合 */
    private List<T> list;
    
    /** 目标实例 */
    private T bean;
    
    /** 用栈来存储XML格式的上下文 */
    private Stack<String> ctx;
    
    /** 用来收集节点值 */
    private StringBuilder sb;
    
    /** 
     * 目标类型,这个变量是必须的,
     * 通过构造器进行约束 
     */
    private Class<T> clazz;
    
    /** 开始封装的标签名 */
    private String startNode;
    
    /** 日志记录器 */
    private final Log logger = LogFactory.getLog(getClass());
    
    public BeanHandlerForSAX(Class<T> clazz)
    {
        this.clazz = clazz;
    }
    
    public BeanHandlerForSAX(Class<T> clazz, String startNode)
    {
        this.clazz = clazz;
        this.startNode = startNode;
    }
    
    /**
     * 取得目标结果集,有可能返回空集合,但不会是空,
     * 所以不会导致空指针异常
     */
    public List<T> getList()
    {
        if (this.list == null)
        {
            return Collections.EMPTY_LIST;
        }

        List<T> beanList = new ArrayList<T>(this.list);
        this.list = null;
        return Collections.unmodifiableList(beanList);
    }
    
    /**
     * Xces解析器默认传递16K
     */
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException
    {
        // 表示找到目标节点,将相应的值进行缓存,每次最大缓存16K,这跟底层解析器有关
        if (ctx != null)
        {
            String tmp = new String(ch, start, length);
            
            // 去除换行,退格,两端空格
            tmp = tmp.replaceAll("\\n|\\t+", "").trim();
            this.sb.append(tmp);
        }
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException
    {
        // 为空表示还未找到目标节点,继续向下寻找
        if (this.ctx.isEmpty())
        {
            return;
        }
        
        // 找到目标节点,出栈进行操作
        String tmp = this.ctx.pop();
        
        // 达到目标节点,将Bean加入List,继续下一个Bean实例的封装
        if (this.startNode.equalsIgnoreCase(tmp))
        {
            list.add(bean);
            newBeanInstance();
            return;
        }
        
        // 属性未遍历完成,将值进行填充
        try
        {
            PropertyDescriptor pd = new PropertyDescriptor(tmp, clazz);
            
            Method writer = pd.getWriteMethod();
            Class<?> type = pd.getPropertyType();
            
            String stringValue = sb.toString();
            Object value = null;
            
            // 将目标串转换成所需要的类型
            value = convert(type, stringValue);
            
            // 如果值不空才进行设值,否则忽略
            if (value != null)
            {
                writer.invoke(bean, value);
            }
        }
        
        // 个别异常将不会影响程序执行流程,内部消化
        catch (IntrospectionException e)
        {
            logger.error(e);
        }
        catch (IllegalArgumentException e)
        {
            logger.error(e);
        }
        catch (IllegalAccessException e)
        {
            logger.error(e);
        }
        catch (InvocationTargetException e)
        {
            logger.error(e);
        }
        catch (Exception e)
        {
            // 发生致命错误,应该通知调用方进行合理处理
            throw new SAXException(e);
        }
        
        // 将节点值重新初始化,避免干扰其他的节点值
        this.sb = new StringBuilder();
        
    }
    
    /**
     * 类型转换器的简单封装
     * @param type 目标类型
     * @param target 目标串
     * 有可能返回空,需要注意
     */
    protected Object convert(Class<?> type, String target)
    {
        Object res = null;
        if (type == String.class)
        {
            res = target;
        }
        else if (type == byte.class)
        {
            res = Byte.valueOf(target);
        }
        else if (type == int.class)
        {
            res = Integer.valueOf(target);
        }
        else if (type == float.class)
        {
            res = Float.valueOf(target);
        }
        else if (type == double.class)
        {
            res = Double.valueOf(target);
        }
        else if (type == boolean.class)
        {
            res = Boolean.valueOf(target);
        }
        else if (type == java.sql.Date.class)
        {
            res = java.sql.Date.valueOf(target);
        }
        else if (type == java.util.Date.class)
        {
            try
            {
                res = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss").parse(target);
            }
            catch (ParseException e)
            {
                logger.error(e);
            }
        }
        return res;
    }

    /**
     * 在文档开始时,进行处理器的初始化工作
     */
    @Override
    public void startDocument() throws SAXException
    {
        this.list = new ArrayList<T>(0);
        this.ctx = new Stack<String>();
        this.sb = new StringBuilder(0);
        newBeanInstance();
        
        // 在默认情况下,将简单类名当作目标节点开始标签
        this.startNode = this.clazz.getSimpleName();
    }

    /**
     * 通过反射,创建一个新的Bean实例
     */
    private void newBeanInstance()
    {
        try
        {
            this.bean = clazz.newInstance();
        }
        catch (InstantiationException e)
        {
            logger.error(e);
        }
        catch (IllegalAccessException e)
        {
            logger.error(e);
        }
    }

    /**
     * 开始元素自动触发,只有在遇到目标节点才处理,
     * 在上下文不空时亦可处理
     */
    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException
    {
        if (this.startNode.equalsIgnoreCase(name) || !this.ctx.isEmpty())
        {
            ctx.push(name);
        }
    }
    
}




解析的XML为:

<?xml version="1.0" encoding="UTF-8"?>
<class>
  <student>
                    <name>Tom Kyte</name>
    <gender>male</gender>
		<job>engineer</job>
		<age>16</age>
		<height></height>
	</student>
	<student>
		<name>Charry</name>
		<gender>female</gender>
		<job>manager</job>
		<age>16</age>
	</student>
</class>


使用方式:

        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
        
        BeanHandlerForSAX<Student> h = new BeanHandlerForSAX<Student>(Student.class);
        xmlReader.setContentHandler(h);
        
        xmlReader.parse("file:c:/t.xml");

        System.out.println(h.getList()); 
        


输出结果:
- java.beans.IntrospectionException: Method not found: isHeight
[{name = Tom Kyte, gender = male, job = engineer, age = 16}, {name = Charry, gender = female, job = manager, age = 16}]



2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics