使用sax解析xml文件,并自动根据实体类class得到映射后的实体类list集合
来源:互联网 发布:linux scp传文件夹 编辑:程序博客网 时间:2024/06/06 11:01
java中的javax.xml.parsers.SAXParser类用于解析xml文件,他是基于事件流形式解析的,其他解析xml的类和jar包还有很多,比如DOM是基于XML文档树结构的解析(代表有dom4j。sax的解析特点,决定其不是很占用太大内存,当然也有弊端,这里只是学习一下sax如何解析xml。
sax解析的一般步骤:
//从流中解析xml文件public List<Book> parse(InputStream is){//得到一个sax解析器工厂SAXParserFactory saxfactory = SAXParserFactory.newInstance();try {//得到sax解析器,并在parse解析方法中传入handler对象辅助解析SAXParser parser = saxfactory.newSAXParser();//实例化一个解析器辅助handler,解析事件处理方法都包含在其中Handler handler = new Handler(Book.class);parser.parse(is, handler);is.close();//返回handler解析后的list集合return handler.getobjs();} catch (Exception e) {e.printStackTrace();}return null;}
自定应一个Handler类继承DefaultHandler类。并且使用反射,来自动映射到对应的实体类,这样,以后解析一个xml,只需要传入指定实体类的class类型,就能返回解析后的实体类的list集合。
这里只是实现了其中的一小部分功能。
import java.io.InputStream;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Stack;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class XmlUtils {private String xmluri;public XmlUtils(){}public XmlUtils(String xmluri){this.xmluri = xmluri;}//测试方法,解析一个urlpublic void parse(){//得到一个sax解析器工厂SAXParserFactory saxfactory = SAXParserFactory.newInstance();try {//得到sax解析器,并在parse解析方法中传入handler对象辅助解析SAXParser parser = saxfactory.newSAXParser();parser.parse(xmluri, new Handler(Book.class));} catch (Exception e) {e.printStackTrace();}}//从流中解析xml文件public List<Book> parse(InputStream is){//得到一个sax解析器工厂SAXParserFactory saxfactory = SAXParserFactory.newInstance();try {//得到sax解析器,并在parse解析方法中传入handler对象辅助解析SAXParser parser = saxfactory.newSAXParser();//实例化一个解析器辅助handler,解析事件处理方法都包含在其中Handler handler = new Handler(Book.class);parser.parse(is, handler);is.close();//返回handler解析后的list集合return handler.getobjs();} catch (Exception e) {e.printStackTrace();}return null;}/** * * @param cls 实体类中方法的形参参数类型 * @param obj实体类set方法传入的参数对象 * @return 根据参数类型转换参数对象值 */private Object changeType(Class<?> cls, Object obj){//根据cls名称获取对应类型枚举值,没有返回EMPTYTypeEnum te = TypeEnum.valueOfTE(cls.getSimpleName());String value = obj.toString();switch (te) {case BOOLEAN:return Boolean.valueOf(value);case BYTE:return Byte.valueOf(value);case CHAR:return value.charAt(0);case DOUBLE:return Double.valueOf(value);case SHORT:return Short.valueOf(value);case FLOAT:return Float.valueOf(value);case INT:return Integer.valueOf(value);case LONG:return Long.valueOf(value);case STRING:return value;default://不对应以上java自带基本类型,返回原始obj对象return obj;}}/** * * @author Administrator * * @param <T> */public class Handler<T> extends DefaultHandler{/** 当前索引的xml标签值 */private String tagname = null;/** 实体类class */private Class<T> cls;/** 保存实体类对象list集合 */private List<T> objs;/** 存放对应实体类和起复合成员变量对象的method[]数组的 hash表 */private Map<Class<?>, Method[]> methodmap;/** 用于保存当前正在操作实体类的栈,里面保存有实体类和其复合成员字段的实体类 */private Stack<Object> stack;/** * * @return 返回解析后的实体类集合 */public List<T> getobjs(){return objs;}/** * 初始化类 * @param cls */public Handler(Class<T> cls){this.cls = cls;this.stack = new Stack<Object>();this.methodmap = new HashMap<Class<?>, Method[]>();this.methodmap.put(cls, cls.getDeclaredMethods());}@Overridepublic void startDocument() throws SAXException {// 开始解析 new一个新集合objs = new ArrayList<T>();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {//根据栈是否为空来获取默认实体类或者字段所对应qName名称的方法Method method = stack.empty() ? getMethod(cls, qName) : getMethod(stack.peek().getClass(), qName);try {if (method != null) {//获取方法形参类型,这里定义set方法只有一个参数Class<?> paramtype = method.getParameterTypes()[0];//获取对应参数类型的枚举值,并设置标签属性值TypeEnum te = TypeEnum.valueOfTE(paramtype.getSimpleName());if (te == TypeEnum.EMPTY) {setAttr(paramtype, attributes);}} else if (cls.getSimpleName().equals(qName)) {//当前标签为实体类标签时,设置实体类对应的xml标签属性值setAttr(cls, attributes);}} catch (Exception e) {e.printStackTrace();}//设置当前索引到的标签tagname = qName;}/** * * @param paramtype 形参类型 * @param attributes 属性值对象 * @throws Exception */private void setAttr(Class<?> paramtype, Attributes attributes) throws Exception{//实例化形参class对应的对象,并入栈stack.push(paramtype.newInstance());if (!methodmap.containsKey(paramtype)) {//如果method的hash表不包含此class的方法,则保存方法数组到hash表methodmap.put(paramtype, paramtype.getDeclaredMethods());}//遍历设置属性值for (int i=0; i < attributes.getLength(); i++) {invokeSetMethod(stack.peek(), attributes.getLocalName(i), attributes.getValue(i));}}@Overridepublic void endDocument() throws SAXException {// 解析结束super.endDocument();}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {//当前标签值是实体类标签,stack出栈,并添加到实体类集合中if (cls.getSimpleName().equals(qName)) {objs.add((T) stack.pop());} else if (!stack.empty()) {try {//当栈不为空时,获取栈顶元素的class名称,判断是否对应qName标签值String clsname = stack.peek().getClass().getSimpleName();if (clsname.equals(qName)) {/* * 第一次弹出栈的obj为实体类对应的set方法的形参对象, * 出栈后,栈顶元素就为调用改set方法的对象。 */Object parent = stack.pop();invokeSetMethod(stack.peek(), qName, parent);}} catch (Exception e) {e.printStackTrace();}}tagname = null;}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {//解析字符内容if (tagname == null) return;String name = null;Method[] methods = stack.empty() ? methodmap.get(cls) : methodmap.get(stack.peek().getClass());//遍历method数组,如果当前tagname标签对应其中一个method,则执行该methodfor (Method method: methods) {name = setMethodName(tagname);if (name.equals(method.getName())) {try {/* * 当前栈顶元素为调用改method方法的对象 * new String(ch, start, length) 为标签值 */invokeSetMethod(stack.peek(), tagname, new String(ch, start, length));break;} catch (Exception e) {e.printStackTrace();}}}}/* * 此方法待合并 * @param name 符合javabean规范的类的方法名 * @return 返回getXXX形式无参数方法名 */private String setMethodName(String name){StringBuilder sb = new StringBuilder(name);//替换首字符为大写char first = sb.charAt(0);sb.setCharAt(0, Character.toUpperCase(first));sb.insert(0, "set");return sb.toString();}/** * * @param obj 执行方法的对象 * @param mname 方法名称 * @param args 方法参数列表 * @throws Exception */private void invokeSetMethod(Object obj, String mname, Object...args) throws Exception{//根据对象class和方法名称获取method,这里指定set方法不重复,并且只有一个形参Method method = getMethod(obj.getClass(), mname);//得到该方法的形参class列表Class<?>[] types = method.getParameterTypes();method.invoke(obj, changeType(types[0], args[0]));}/** * * @param cls 获取method的class类 * @param name 方法名称 * @return 返回获取的method,没有则返回null */private Method getMethod(Class<?> cls, String name){name = setMethodName(name);//在已有的method数组hash表中获取已经保存的方法数组Method[] methods = methodmap.get(cls);for (Method method: methods) {if (name.equals(method.getName())) {return method;}}return null;}}}
- 使用sax解析xml文件,并自动根据实体类class得到映射后的实体类list集合
- Xml解析之Sax解析(传入xml即可得到实体类集合)
- java中使用sax解析xml,以实体类集合的方式接受xml解析的值
- java 根据实体类创建映射文件
- 使用mybatis generater 自动生成实体类和映射文件
- DOM4j解析xml文件(SaxReader方法),并抽象实体类
- java根据条件删除list集合中的实体类!
- Hibernate实体类映射文件demo.hbm.xml 中的<generator class="?"></generator>的不同属性含义
- 根据Hibernate映射文件和实体类生成数据库
- Hibernate 根据实体映射文件自动生成表
- 实体类和映射文件
- 使用Mybatis生成工具自动生成实体类和对应的mapper映射文件以及接口文件
- 用MyEclipse自动生成hibernate映射文件和实体类
- Myeclipse 自动生成hibernate实体类和映射文件步骤
- 用MyEclipse自动生成hibernate映射文件和实体类
- 用MyEclipse自动生成hibernate映射文件和实体类
- MyBatis之自动生成实体类及映射文件《二》
- MyBatis逆向工程自动生成实体类和映射文件
- 由调用方或被调用方保存的寄存器
- -in 与 -notin 操作符的应用
- 参数传递
- 结构对齐示例
- 可以上传、下载文件的SSH客户端软件--SecureCRT绿色版
- 使用sax解析xml文件,并自动根据实体类class得到映射后的实体类list集合
- 寄居蟹与海葵
- 关于wamp启动是80端口被占用的问题详解(win7系统下WAMP 80端口被Microsoft-HTTPAPI/2.0占用的解决办法)
- 引用&
- css3新属性text-shadow
- 64位配置的程序(Visual C++)
- 错误160源文件"C:\Users\Administrator\AppData\Local\Temp\2\.NETFramework,Version=v4.0.AssemblyAttributes
- JAVA的Date类与Calendar类【转】
- 用分析服务SSAS解决占比、同比和环比问题