前言:

        Lrmx文件本质就是读取xml文件,数据库字段设计和类的属性设计都xml中节点保持了一致。那么就可以用类的反射来实现给字段赋值,这样可以大大节省代码的编写量。


一、加载文件并遍历所有的节点:       

 File f = new File(this.LrmxFilePath);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建一个DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 使用DocumentBuilder对象的parse方法解析XML文件,得到一个Document对象
            org.w3c.dom.Document document = builder.parse(f);
            // 获取根节点
            Element root = document.getDocumentElement();
            NodeList nl = root.getChildNodes();
   

        使用记事本打开lrmx文件,我们可以看到我们需要的内容都在Person节点的子节点下,除了家庭成员外信息还有子节点,其他包括简历、考核情况、奖惩都是放在一个子节点信息里面。

干部任免审批表管理系统(三) 读取Lrmx格式文件数据并存储到实体类中-LMLPHP

二、通过反射给对象赋值

        遍历所有子节点,对于简历、家庭成员做特殊处理。Person 是定义的类,属性就是对应所有节点。另外还定义有类  JianLi ,JiaTingChengYuan  对于奖惩记录和 年度考核结果这里暂时不做处理。

     1. 遍历子节点,对于子节点名称不是 #text 的做处理   

    for (int i = 0; i < nl.getLength(); i++) {   //循环遍历
                if (!nl.item(i).getNodeName().equals("#text")  ) {
//只处理节点名称不是 #text 的
    //后续处理逻辑放在此处          
}
}

        2.  通过反射获取属性的set方法

String name = nl.item(i).getNodeName();
                    Field field = p.getClass().getDeclaredField(name);
                    name = name.substring(0, 1).toUpperCase() + name.substring(1);
                    Method m = p.getClass().getDeclaredMethod("set" + name, field.getType());

        属性的set方法都是  set + 属性名称,属性名称第一个字符需要大写。通过类的.getClass().getDeclareField(name) 获取到属性, 通过 getClass().getDeclaredMethod("set" +name, field.getType())  来获取到方法,在通过调用invoke方法来给类实体赋值。

 m.invoke(p, nl.item(i).getTextContent());

        3.  简历的处理:

        正常填写一行就是一段简历,对应数据库中简历表就是一条记录。首先定义一个list用来存放建立的记录了。        

 List<JianLi> jianLiList = new ArrayList<>();

        定义一个字符串,用来接收xml中建立内容       

   String JianLi = nl.item(i).getTextContent();

        如果正常填写,那么用换行符“\n” 既可以那倒1行行简历的数据。但是也存在有不正常的现象,往往会一行经历显示不全,那么就会分成两行,如果用“\n”换行,会错误的认为是两条经历,而实际上是上一条经历没有写完,这里就要做个特殊处理了。我的处理是,正常简历一行记录的开头是以年开始如:

        那么就判断拿到的行数据不是以数字开头,就判断位上一条经历没有写完,需要把这行内容补充回上一条经历。

        处理建立还有一个难点就是需要分割出 起始日期以及工作经历。首先用空格进行分割,认为空格前面的就是起止时间,后面的就是经历。起止时间通过“-” 或者“--” 来做分割,前面的是开始,后面的是截止。 对于最后一段经历,终止时间是空或者些至今.那么久截止日期设置为空即可,对于日期这里的处理需要根据不同情况来做if处理了.

        4.  家庭成员信息的处理:

         这里本身填写的时候就是一行一行的, 不知道为什么这么多版本的简历填写不能做下规范,家庭成员的处理就没有太多特别的. 就是JiaTingChengYuan 这个节点再去遍历他的子节点,同样是用反射的手段来给类赋值. 其中对于出生年月的填写要做些判断了.               

  if (name.equals("JiaTingChengYuan")) {
                        //家庭成员信息
                        NodeList nl2List = nl.item(i).getChildNodes();
                        List<JiaTingChengYuan> jtcyList = new ArrayList<>();
                        for (int j = 0; j < nl2List.getLength(); j++) {
                            if (!nl2List.item(j).getNodeName().equals("#text")) {
                                JiaTingChengYuan jtcy = new JiaTingChengYuan();
                                NodeList nl3 = nl2List.item(j).getChildNodes();
                                for (int k = 0; k < nl3.getLength(); k++) {
                                    if (!nl3.item(k).getNodeName().equals("#text")) {
                                        String name2 = nl3.item(k).getNodeName();
                                        Field field2 = jtcy.getClass().getDeclaredField(name2);
                                        name2 = name2.substring(0, 1).toUpperCase() + name2.substring(1);
                                        Method m2 = jtcy.getClass().getDeclaredMethod("set" + name2, field2.getType());
                                        m2.invoke(jtcy, nl3.item(k).getTextContent().trim());
                                    }
                                }
                                jtcy.setChuShengRiQi(jtcy.getChuShengRiQi().trim().replaceAll("\n",""));
                                if (!jtcy.getChuShengRiQi().equals("") && ( jtcy.getChuShengRiQi().length() == 6 || jtcy.getChuShengRiQi().length() == 8)) {
                                    jtcy.setNianLing(JiSuanNianLing(p, jtcy.getChuShengRiQi()));
                                }
                                jtcyList.add(jtcy);
                            }
                        }
                        p.setJiaTingChengYuan(jtcyList);
                    }

三、完整的for循环处理代码:

 for (int i = 0; i < nl.getLength(); i++) {
                if (!nl.item(i).getNodeName().equals("#text")  ) {
                    String name = nl.item(i).getNodeName();
                    Field field = p.getClass().getDeclaredField(name);
                    name = name.substring(0, 1).toUpperCase() + name.substring(1);
                    Method m = p.getClass().getDeclaredMethod("set" + name, field.getType());
                    if (!name.equals("JianLi") && !name.equals("JiaTingChengYuan")) {   //简历和家庭成员需要做特殊的处理
                      if(nl.item(i).getTextContent().trim().equals("\r\n") || nl.item(i).getTextContent().trim().equals("\n") || nl.item(i).getTextContent().equals("\n  ")  ){
                          m.invoke(p,"");
                      }else{
                        m.invoke(p, nl.item(i).getTextContent());}
                    }
                    if (name.equals("JianLi")) {
                        List<JianLi> jianLiList = new ArrayList<>();
                        String JianLi = nl.item(i).getTextContent();
                        int rowNums =0;
                        String[] JianLiArrayTmp = JianLi.split("\n");  //调试表明用的\n
                        List<String>  JianLiArray = new ArrayList<>();

                        for (String s: JianLiArrayTmp){
                            if(!s.replaceAll("\n","").trim().equals("")){
                                JianLiArray.add(s);
                            }
                        }
                        for (String line : JianLiArray) {
                            if (!line.trim().equals("")) {

                                if(!Tools.isStartWithNumber(line.trim())){   //如果行不是以数字开头那么就将简历附加到上一条
                                    jianLiList.get(rowNums -1).setJingLi(jianLiList.get(rowNums -1).getJingLi() + " " + line.trim());

                                    continue;
                                }

                                JianLi jl = new JianLi();
                                String[] partArray = line.split(" ");


                                    int tmpNum = 0;
                                    String jingli = "";
                                    for (String s : partArray) {
                                       if(tmpNum ==0){
                                           //第一列分割的用来做时间拆分
                                           String[] a ;
                                           a = s.split("--|——");

                                           if(a.length ==1){
                                               a = s.split("-|—");
                                           }
                                           jl.setKaiShiNianYue(a[0].trim());
                                           if(a.length ==1){

                                               jl.setJieSuNianYue("");
                                           }else{

                                               jl.setJieSuNianYue(a[1].trim());
                                           }

                                           tmpNum ++ ;
                                       }else{
                                           //且他都用来做经历
                                           jingli +=s.trim();
                                       }
                                    }

                                    jl.setJingLi(jingli);



                                jianLiList.add(jl);
                                rowNums ++;
                            }

                        }


                        p.setJianLi(jianLiList);

                    }
                    if (name.equals("JiaTingChengYuan")) {
                        //家庭成员信息
                        NodeList nl2List = nl.item(i).getChildNodes();
                        List<JiaTingChengYuan> jtcyList = new ArrayList<>();
                        for (int j = 0; j < nl2List.getLength(); j++) {
                            if (!nl2List.item(j).getNodeName().equals("#text")) {
                                JiaTingChengYuan jtcy = new JiaTingChengYuan();
                                NodeList nl3 = nl2List.item(j).getChildNodes();
                                for (int k = 0; k < nl3.getLength(); k++) {
                                    if (!nl3.item(k).getNodeName().equals("#text")) {
                                        String name2 = nl3.item(k).getNodeName();
                                        Field field2 = jtcy.getClass().getDeclaredField(name2);
                                        name2 = name2.substring(0, 1).toUpperCase() + name2.substring(1);
                                        Method m2 = jtcy.getClass().getDeclaredMethod("set" + name2, field2.getType());
                                        m2.invoke(jtcy, nl3.item(k).getTextContent().trim());
                                    }
                                }
                                jtcy.setChuShengRiQi(jtcy.getChuShengRiQi().trim().replaceAll("\n",""));
                                if (!jtcy.getChuShengRiQi().equals("") && ( jtcy.getChuShengRiQi().length() == 6 || jtcy.getChuShengRiQi().length() == 8)) {
                                    jtcy.setNianLing(JiSuanNianLing(p, jtcy.getChuShengRiQi()));
                                }
                                jtcyList.add(jtcy);
                            }
                        }
                        p.setJiaTingChengYuan(jtcyList);
                    }
                }

总结:

        在这种属性繁多,如果一一些set那么代码量会很多。通过反射的功能,能够大大节约代码量。后续很多处理主要是考虑到一些录入场景不规范的问题的处理了。

04-07 19:51