zoukankan      html  css  js  c++  java
  • java---解析XML文件,通过反射动态将XML内容封装到一个类中

    本博客讲的XML解析,使用的是dom4j。

    首先建立一个maven项目,在dom.xml中引入相应的dom4j的版本。作者下载的是热度很高的1.6.1版本。maven的使用在这里不做详细讲解。

    引入成功后,来简单了解该包提供的API

    1.org.dom4j.io.SAXReader.class-----该类提供了reader方法,可以将xml文件读取为Document对象,该方法返回值类型为Document

    2.org.dom4j.Document.class----------该类提供了getRootElement方法,可以获得Document对象的根节点,此方法返回值类型是Element

    3.org.dom4j.Element-------该类提供了elements方法,获取所有的子节点,返回值类型为Element;

                    attributeValue方法,获得通过属性名节点的属性值,返回值类型为String

                    getStringValue()方法,获得element的文本值,返回值类型为String

    下面使用上述方法来解析XML文件。

    一:新建或者自己导如XML文件。作者为了方便演示,新建一个新的XML文件,如下。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <students>
        <student id="1">
            <name>Claire</name>
            <age>18</age>
            <gender>女</gender>
        </student>
        <student id="2">
            <name>Leafly</name>
            <age>18</age>
            <gender>男</gender>
        </student>
        <student id="3">
            <name>Dingdang</name>
            <age>18</age>
            <gender>男</gender>
        </student>
        <student id="4">
            <name>DingDing</name>
            <age>18</age>
            <gender>男</gender>
        </student>
        <student id="5">
            <name>DangDang</name>
            <age>18</age>
            <gender>女</gender>
        </student>
    
    </students>

    2.将上述xml文件放到src下面。

    3.创建一个Student类,其属性与上述xml中的元素一致。

    public class Student {
        //private static final int AAA = 1;
        private String id;
        private String name;
        private String age;
        private String gender;
        
        
        //构造
        
        public Student() {
            
        }
        
        public Student(String id, String name, String age, String gender) {
            super();
            this.id = id;
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        
        
    
    
    
        //getter setter
        public String getId() {
            return id;
        }
        
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        public String getGender() {
            return gender;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
    
    
        
        
        //toString
        @Override
        public String toString() {
            return "Student [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "]";
        }
        
    
    }

    4.创建新类ReadXMl,在该类中创建方法来解析XML文件。

        private static void readXmlFun() throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
            
            
            //1.反射,得到类的引用
            Class student = Class.forName("readXmlAndReflect.Student");
            //通过类的引用,得到类的对象
            Object stuInstance = student.newInstance();
            //创建一个list 来放多个student的对象
            List<Student> students = new ArrayList<Student>();
            
            SAXReader reader = new SAXReader();
            //将XML文件读取为一份document对象
            Document document = reader.read(readXmlFun.class.getResourceAsStream("/StudentDate.xml"));
            //利用Document类中的方法,获取根节点.返回的是Element
            Element rootElement = document.getRootElement();
            
            //利用Element中的方法,获取根节点下的全部子节点.返回一个List<element>
            List<Element> elements = rootElement.elements();
            
            //利用Element中的方法,获取子 节点中的属性(StudentData中的属性为id)
            //1.遍历list,获得每个元素
            for (Element element : elements) {
                System.out.println("---------------------------------");
                //遍历并得到每个元素执行属性名称的属性值
                String stuId = element.attributeValue("id");
                System.out.println("学生id为"+ stuId);
                //遍历并获得每个元素的全部子节点,返回一个List<element>
                List<Element> subElement = element.elements();
                
            
                //通过方法名反射出方法对象
                Method method2 = student.getDeclaredMethod("setId", String.class);
                //通过反射调用方法,stuInstance对象调用method,参数为stuData---相当于给各参数赋值
                method2.invoke(stuInstance, stuId);
                
                for (Element subElementData : subElement) {
                    //得到每个子节点的名字
                    String elementName = subElementData.getName();
                    //遍历并获得每个子元素的文本内容,如得到name子节点的文本值为Claire
                    String stuData = subElementData.getStringValue();
                    System.out.println(elementName +"为" + stuData);
                    
                    
                    //通过elemetname得到对应的get set方法,先拼接出方法名,比如 name--setName
                    String funName = "set" + (elementName.charAt(0)+"").toUpperCase()+elementName.substring(1);
                
                    //通过方法名反射出方法对象
                    Method method1 = student.getDeclaredMethod(funName, String.class);
                    //通过反射调用方法,调用stuInstance对象的method方法,参数为stuData---给各属性赋值
                    method1.invoke(stuInstance, stuData);
                }
                //将每个学生对象添加到list列表中
                students.add((Student)stuInstance);
                System.out.println(students);
            
            }
        }

     这里解释下,上面使用的

    Document document = reader.read(readXmlFun.class.getResourceAsStream("/StudentDate.xml"));
    前面加上/------------代表在当前类的src下面找


    如果没有/--------------代表在跟类同级的目录下找。








    可以看到上面使用了反射。利用反射可以动态的为每一个Student对象赋值。当我们的XML文件改变,添加或删除了新的属性之后,完全不需要去修改我们的ReadXML类,只在Student类中添加或删除对应的属性即可。实现了解耦。

     我们经常通过反射来做下面的事情:

    1.获取到某各类的引用

      通常有3种方式:

        1.Class clazz = Class.forName(" 这里必须是类全名");

        2.我们每一个类都有一个静态的class属性:Class clazz =类名A.Class(这个与第一种方式的区别是,不会去运行类A中的静态代码块);

        3.每个类都有一个getClass()方法: classA a = new ClassA(); Class clazz =a.getClass();

    2.通过该类的引用获取类的对象

      object o = clazz.newInstance();

    3.通过该类的引用获取属性

      

    4.通过该类的引用获取所有方法(普通/构造)

    下面代码详细说明了反射机制中常用的方法,有兴趣可以了解下:

    package readXmlAndReflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.sql.Types;
    
    public class Reflect {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
            Class clazz = Class.forName("readXmlAndReflect.Student");
            //创建对象
            Object o =clazz.newInstance();
            
            
            //创建一个stringBuffer
            StringBuffer buffer = new StringBuffer();
            
            //类 public class readXmlAndReflect.Student{}
            buffer.append("
    "+"-------------class-------------------"+"
    ");
            buffer.append(Modifier.toString(clazz.getModifiers()) + " class " + clazz.getName()+"{"+"
    ");
            
            //
            buffer.append("
    "+"-------------field-------------------"+"
    ");
            //获取所有声明的属性,包括私有和常量
            Field[] fields = clazz.getDeclaredFields();
            //遍历所有的属性
            for (Field field : fields) {
                //获取属性的修饰符 如public static 
                buffer.append("	" + Modifier.toString(field.getModifiers()));
                //获取属性的类型 如 string int getType()获取到的类全名(如java.lang.String),想要获得简单类型名如String,可以使用Class类中getSimpleName()方法
                buffer.append("	" + field.getType().getSimpleName());
                //获取属性名称
                buffer.append("	" + field.getName());
                buffer.append(";"+"
    ");
                
                //得到域之后有什么用呢?
                //我们可以直接使用得到的域给其赋值或读取域的值,由于域都是私有的,这里需要利用反射打破类的封装
                field.setAccessible(true);//如果没有这一句,运行时会报错java.lang.IllegalAccessException:
                //给对象0的域field 赋值为"3"
                field.set(o, "3");
                //获取 对象o 的 域field 的值
                System.out.println(field.get(o));
                
            }
            
            
            
        
            
            //方法 如 public static string function(){}
            buffer.append("
    "+"-------------function-------------------"+"
    ");
            //获得所有声明的方法,包括private
            Method[] motheds = clazz.getDeclaredMethods();
            
            for (Method method : motheds) {
                //获得方法的修饰符 如 public static 
                buffer.append("	"+Modifier.toString(method.getModifiers()) + " ");
                //获得方法的返回值类型
                buffer.append(method.getReturnType().getSimpleName()+" ");
                //获得方法名
                buffer.append(method.getName() + "(");
                //获得方法的参数类型,可能有多个参数,所以返回值为一个数组
                Class[] parameterTypes = method.getParameterTypes();
                //遍历方法的参数类型
                for (Class parameterType : parameterTypes) {
                    //遍历获得每一个参数类型
                    buffer.append(parameterType.getSimpleName()+", ");
                }
                buffer.append(") { }"+"
    ");
                
            }
            
            
            //获得方法有什么用??通常用来调用方法
            //1.先通过方法名来获得一个方法
            Method setNameFun = clazz.getMethod("setName", String.class);
            //可以直接调用,调用方法method---调用o对象的setNameFun方法,参数为“小笨蛋”
            setNameFun.invoke(o, "小笨蛋");
            
            
            //构造方法
            buffer.append("
    " + "-------------constructions-------------------"+"
    ");
            Constructor[] constructors = clazz.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                
                buffer.append(Modifier.toString(constructor.getModifiers()) + " ");
                buffer.append(constructor.getName() + " (");
                Class[] parametertypes = constructor.getParameterTypes();
                for (Class parametertype : parametertypes) {
                    buffer.append(parametertype.getSimpleName() +",");
                }
                buffer.append(") { }"+"
    ");
            }
            
            buffer.append("}");
            
            System.out.println(buffer);
        }
    
    }
  • 相关阅读:
    关于字体单位em的问题
    键盘按钮keyCode大全
    右侧导航栏(动态添加数据到list)
    当前页面点击取到值
    前端写分页(用了自己同事写的插件)
    选择控件js插件和使用方法
    Form表单验证
    前端页面跳转并取到值
    App配置页面头部
    json字符串、json对象、数组之间的转换
  • 原文地址:https://www.cnblogs.com/clairejing/p/9377293.html
Copyright © 2011-2022 走看看