`
yunchow
  • 浏览: 324361 次
  • 性别: 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
分享到:
评论

相关推荐

    SAX解析XML文件实例

    SAX解析XML文件的实例。一个项目同时用dom解析和sax解析xml文件貌似会报错,项目框架建一直是用sax和dom4j解析xml文件的。当我用dom解析xml文件。导入包后就报错识别不了xml文件的编码格式。于是做了一个sax解析xml...

    SAX解析XML实例

    总的来说,SAX解析XML是一种高效且灵活的方法,适用于处理大型XML文档。通过自定义事件处理器,我们可以根据业务需求定制解析逻辑,从而有效地解析和利用XML数据。在实际项目中,结合源码分析和工具使用,如IDE中的...

    sax解析xml实例

    ### SAX 解析 XML 实例详解 #### 一、SAX 解析器简介 SAX (Simple API for XML) 是一种基于事件驱动模型的 XML 解析技术。与 DOM (Document Object Model) 解析不同,SAX 不会将整个 XML 文档加载到内存中,而是...

    读取RSS-SAX解析XML实例(java版)

    标题"读取RSS-SAX解析XML实例(java版)"所涉及的知识点主要集中在两个方面:一是如何读取RSS(Really Simple Syndication)数据,二是使用SAX解析XML文件。 RSS是一种用于发布新闻、博客和其他定期更新内容的格式...

    Servlet利用SAX解析XML文档

    本主题将深入探讨如何在Servlet中利用SAX解析XML文档。 首先,我们需要了解SAX解析的基本原理。SAX解析器不创建整个XML文档树,而是当遇到XML文档的各个部分(如元素、属性、文本等)时,触发相应的事件回调函数。...

    android 使用Sax解析XML 源码实例

    下面是一个SAX解析XML的示例(有点长,因为详细注解了SAX事件处理的所有方法),SAX API中主要有四种处理事件的接口,它们分别是ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler 。下面的例子可能...

    Sax解析xml文件

    以下是一个使用SAX解析XML文件的基本步骤: 1. **创建解析器**: 首先,我们需要创建一个SAX解析器实例。在Java中,这通常通过`SAXParserFactory`类完成。设置解析器属性,然后调用`newSAXParser()`方法获取`...

    sax解析xml尤其是获取元素的值或者内容

    在使用SAX解析XML前,需要创建一个解析器实例。Java中,可以使用`SAXParserFactory`来生成`SAXParser`,然后调用`parse()`方法解析XML文件。例如: ```java SAXParserFactory factory = SAXParserFactory.new...

    sax解析xml文件

    总结来说,"saxloadxml"项目提供了使用SAX解析XML文件的一个实例,可以帮助开发者了解如何利用SAX解析器处理XML文档,尤其是在性能和内存使用方面有较高要求的情况下。通过学习和实践这个项目,你可以提升处理XML...

    Android SAX、DOM、Pull解析xml文件案例讲解

    以下是使用SAX解析XML的基本步骤: - 创建`DefaultHandler`子类,重写关键方法如`startElement`、`endElement`和`characters`。 - 实例化`SAXParserFactory`,然后获取`SAXParser`。 - 使用`parse`方法解析XML文件...

    sax解析xml本地读取xml

    标题“sax解析xml本地读取xml”指的是使用SAX解析器来读取和解析存储在本地文件系统中的XML文件。这种方式适用于处理那些无法一次性加载到内存中的大型XML文档,或者对于内存有限的环境。 SAX解析的基本工作原理...

    一个关于sax解析xml的demo

    这个"Project1231_001_XML_SAX"可能包含了一个简单的XML文件和对应的SAX解析示例代码,通过运行这个项目,开发者可以了解如何在实际应用中使用SAX解析XML数据,以及如何处理XML文档中的不同结构。学习和理解SAX解析...

    java解析xml数据---sax解析器

    以下是使用SAX解析XML的基本步骤: 1. 创建一个实现DefaultHandler或ContentHandler接口的类,重写其中的方法,如startElement()、endElement()和characters(),用于处理XML文档的结构和数据。 2. 实例化SAX解析器...

    sax解析xml

    下面我们将深入探讨SAX解析XML的相关知识点。 1. **SAX解析器的初始化**:在Java中,我们通常使用`org.xml.sax.parsers.SAXParserFactory`类来创建并配置SAX解析器。首先,我们需要实例化一个SAXParserFactory对象...

    anroid SAX解析xml文件及实例

    以下是对SAX解析XML在Android中的详细解释以及实例代码分析。 **一、SAX解析XML原理** 1. **事件驱动**:SAX解析器在读取XML文档时,会调用预先定义好的处理器接口(如`DefaultHandler`)中的方法,如`...

    Dom,Sax,Xpath解析XML实例

    在实际开发中,XPath常与DOM或SAX结合使用,先由DOM或SAX解析XML,然后用XPath进行查询。 实例应用: 假设我们有一个XML文件,内容如下: ```xml &lt;name&gt;John Doe &lt;position&gt;Manager &lt;name&gt;Jane Smith ...

Global site tag (gtag.js) - Google Analytics