POI生成word文档完整案例及讲解

  • 作者: 凯哥Java(公众号:凯哥Java)
  • 网络文章
  • 时间:2018-09-25 12:21
  • 6490人已阅读
简介 一,网上的API讲解其实POI的生成Word文档的规则就是先把获取到的数据转成xml格式的数据,然后通过xpath解析表单式的应用取值,判断等等,然后在把取到的值放到word文档中,最后在输出来。1.1,参考一1、poi之word文档结构介绍之正文段落一个文档包含多个段落,一个段落包含多个Runs,一个Runs包含多个Run,Run是文档的最小单元获取所有段落:List<XWPFParagr

🔔🔔好消息!好消息!🔔🔔

 如果您需要注册ChatGPT,想要升级ChatGPT4。凯哥可以代注册ChatGPT账号代升级ChatGPT4

有需要的朋友👉:微信号 kaigejava2022

一,网上的API讲解

其实POI的生成Word文档的规则就是先把获取到的数据转成xml格式的数据,然后通过xpath解析表单式的应用取值,判断等等,然后在把取到的值放到word文档中,最后在输出来。

1.1,参考一

1、poi之word文档结构介绍之正文段落

一个文档包含多个段落,一个段落包含多个Runs,一个Runs包含多个Run,Run是文档的最小单元

获取所有段落:List<XWPFParagraph> paragraphs = word.getParagraphs();

获取一个段落中的所有Runs:List<XWPFRun> xwpfRuns = xwpfParagraph.getRuns();

获取一个Runs中的一个Run:XWPFRun run = xwpfRuns.get(index);

2、poi之word文档结构介绍之正文表格

一个文档包含多个表格,一个表格包含多行,一行包含多列(格),每一格的内容相当于一个完整的文档

获取所有表格:List<XWPFTable> xwpfTables = doc.getTables();

获取一个表格中的所有行:List<XWPFTableRow> xwpfTableRows = xwpfTable.getRows();

获取一行中的所有列:List<XWPFTableCell> xwpfTableCells = xwpfTableRow.getTableCells();

获取一格里的内容:List<XWPFParagraph> paragraphs = xwpfTableCell.getParagraphs();

之后和正文段落一样

注:

  1. 表格的一格相当于一个完整的docx文档,只是没有页眉和页脚。里面可以有表格,使用xwpfTableCell.getTables()获取,and so on

  2. 在poi文档中段落和表格是完全分开的,如果在两个段落中有一个表格,在poi中是没办法确定表格在段落中间的。(当然除非你本来知道了,这句是废话)。只有文档的格式固定,才能正确的得到文档的结构

3、poi之word文档结构介绍之页眉:

一个文档可以有多个页眉(不知道怎么会有多个页眉。。。),页眉里面可以包含段落和表格

获取文档的页眉:List<XWPFHeader> headerList = doc.getHeaderList();

获取页眉里的所有段落:List<XWPFParagraph> paras = header.getParagraphs();

获取页眉里的所有表格:List<XWPFTable> tables = header.getTables();

之后就一样了

4、poi之word文档结构介绍之页脚:

页脚和页眉基本类似,可以获取表示页数的角标

 

1.2,参考二

POI操作Word简介

POI读写Excel功能强大、操作简单。但是POI操作时,一般只用它读取word文档,POI只能能够创建简单的word文档,相对而言POI操作时的功能太少。

(2)POI创建Word文档的简单示例

  1. XWPFDocument doc = new XWPFDocument();// 创建Word文件

  2. XWPFParagraph p = doc.createParagraph();// 新建一个段落

  3. p.setAlignment(ParagraphAlignment.CENTER);// 设置段落的对齐方式

  4. p.setBorderBottom(Borders.DOUBLE);//设置下边框

  5. p.setBorderTop(Borders.DOUBLE);//设置上边框

  6. p.setBorderRight(Borders.DOUBLE);//设置右边框

  7. p.setBorderLeft(Borders.DOUBLE);//设置左边框

  8. XWPFRun r = p.createRun();//创建段落文本

  9. r.setText("POI创建的Word段落文本");

  10. r.setBold(true);//设置为粗体

  11. r.setColor("FF0000");//设置颜色

  12. = doc.createParagraph();// 新建一个段落

  13. = p.createRun();

  14. r.setText("POI读写Excel功能强大、操作简单。");

  15. XWPFTable table= doc.createTable(3, 3);//创建一个表格

  16. table.getRow(0).getCell(0).setText("表格1");

  17. table.getRow(1).getCell(1).setText("表格2");

  18. table.getRow(2).getCell(2).setText("表格3");

  19. FileOutputStream out = newFileOutputStream("d:\\POI\\sample.doc");

  20. doc.write(out);

  21. out.close();

(3)POI读取Word文档里的文字

  1. FileInputStream stream = newFileInputStream("d:\\POI\\sample.doc");

  2. XWPFDocument doc = new XWPFDocument(stream);// 创建Word文件

  3. for(XWPFParagraph p : doc.getParagraphs())//遍历段落

  4. {

  5.  System.out.print(p.getParagraphText());

  6. }

  7. for(XWPFTable table : doc.getTables())//遍历表格

  8. {

  9.  for(XWPFTableRow row : table.getRows())

  10.  {

  11.  for(XWPFTableCell cell : row.getTableCells())

  12.  {

  13.  System.out.print(cell.getText());

  14.  }

  15.  }

 

1.3,参考三,分段混乱

 

题:在操作POI替换world时发现getRuns将我们预设的${product}自动切换成了

 ${product, }]${product  }
成了两个部分

解决方法一。(未尝试) 
强制把List中的内容合并成一个字符串,替换内容后,把段落中的XWPFRun全部remove掉,然后新建一个含有替换后内容的XPWFRun,并赋给当前段落。 
解决方法二. 
请用复制粘贴把你的${product}添加进world文档里面即可解决,不要手打 目前发现复制粘贴是没有问题的,感觉像是poi的一个bug不知道立贴为证。

注意:${这里尽量不要存中文,否在还出现上面情况}

二,项目应用

2.1,判断生成word的条件

private boolean getXpathRes(String json,String xpathRule){
        boolean isTrue = false;
        try {
            JSONObject obj = getGoodJson(json, json.replaceAll("\n", "").replaceAll("\"null\"", "\"\"").replaceAll(":null,", ":\"\",").replaceAll(" \"", "\""));
            XMLSerializer serializer = new XMLSerializer();
            String xml = serializer.write(obj,"UTF-8");
            log.info("测试用的,记得删除"+xml);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            DocumentBuilder db;
            db = dbf.newDocumentBuilder();
            StringReader stringReader = new StringReader(xml);
            InputSource inputSource = new InputSource(stringReader);
            Document doc;
            doc = db.parse(inputSource);
            XPathFactory factory = XPathFactory.newInstance();
            XPath  xpath = factory.newXPath();
            isTrue = (Boolean) xpath.evaluate(xpathRule, doc,XPathConstants.BOOLEAN);
        } catch (Exception e) {
            log.info("合同解析生成XML报错:"+e.getMessage());
        }finally{
            return isTrue;
        }
//        return true;
    }

 

2.1.1,下面就是根据从数据库中取到值,判断规则,和json数据做对比的,就是json数据中有没有数据库中要的值。判断规则是xpath的规则运算符。

 

JSONObject obj = getGoodJson(json, json.replaceAll("\n", "").replaceAll("\"null\"", "\"\"").replaceAll(":null,", ":\"\",").replaceAll(" \"", "\""));
XMLSerializer serializer = new XMLSerializer();
String xml = serializer.write(obj,"UTF-8");

--把json格式的数据以xml的格式输出

首先得到:得到 DOM 解析器的工厂实例 
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

然后从 DOM 工厂获得 DOM 解析器

dbf.setValidating(false);默认是false
DocumentBuilder db;
db = dbf.newDocumentBuilder();

当你有一组应用程序接口(API)只允许用Writer或Reader作为输入,但你又想使用String,这时可以用StringWriter或StringReader。
当读入文件时也一样。可以用StringReader代替Reader来哄骗API,而不必非得从某种形式的文件中读入。StringReader的构造器要求一个String参数。例如:xmlReader.parse(new InputSource(new StringReader(xmlStr)));
StringReader stringReader = new StringReader(xml);


--- 把符合xml的String转成document对象被java程序解读
StringReader stringReader = new StringReader(xml);
InputSource inputSource = new InputSource(stringReader);
Document doc;
doc = db.parse(inputSource);


--用xpath解析
--生成xpath对象
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();


在 Java 中计算 XPath 表达式时,第二个参数指定需要的返回类型。有五种可能,都在javax.xml.xpath.XPathConstants 类中命名了常量:

XPathConstants.NODESET
XPathConstants.BOOLEAN
XPathConstants.NUMBER
XPathConstants.STRING
XPathConstants.NODE 获取节点 node.getTextContent() 获得节点的内容
xpathRule:数据库中存储的
//industrySubType!='20' and //industrySubType!='21' and //industrySubType!='22' and //industrySubType!='23' and //industrySubType!='26' and //industrySubType!='27' and //industrySubType!='28' and //industrySubType!='29' and //industrySubType!='30' and //industrySubType!='148' and //industrySubType!='31' and //industrySubType!='32' and //industrySubType!='37' and //industrySubType!='38' and //industrySubType!='39' and //industrySubType!='11' and //industrySubType!='12' and //industrySubType!='13' and //industrySubType!='14' and //industrySubType!='15' and //industrySubType!='16'

//标示节点中的所有的xml节点
doc就是经过一系列处理,把json数据转化成document对象,并且能被xpath解读的对象:

XPathConstants.BOOLEAN:是返回值,有这个数据就返回true,没有就是false
isTrue = (Boolean) xpath.evaluate(xpathRule, doc,XPathConstants.BOOLEAN);

 

这里需要见xpath的解析规则

xml的xPath解析规则

2.2,获取模板之后,开始获取里面的参数,这个参数是在数据库中配置的。

private List<Map<String,Object>> getTemplateParam(List<String> templatNameList,
        String workOrderId, String productCode,String contractNum,long merchantCode,boolean isMainFlag) throws Exception 
    {
        log.info("======获取模板原始参数开始===获得的模板有templatNameList=="+templatNameList.toString()+"======");
        List<EcontractTemplateParamsqlAdvanced> aTemplateParamSqlList = new ArrayList<EcontractTemplateParamsqlAdvanced>();
        List<Map<String,Object>> aTemplateParamList = new ArrayList<Map<String,Object>>();
        
        List<EcontractTemplateParamAdvanced> orginParamList = new ArrayList<EcontractTemplateParamAdvanced>();

        Map<String, Object> rsMap = null;
        Map<String,Object> queryTemplateParamSql = new HashMap<String,Object>();
        Map<String,Object> queryOriginParam = new HashMap<String,Object>();

        //获取每个模板的参数 
        for(String templateName : templatNameList)
        {
            log.info("======获取模板原始参数中===获得的模板有templatNameList=="+templatNameList.toString()+"==成功获取到模板文档====");
            queryOriginParam.put("templateName", templateName.split(",")[0]);
            //aTemplateParamSqlList = econtractTemplateParamsqlAdvancedService.queryEcontractTemplateParamsqlAdvancedByMap(queryTemplateParamSql);
            //获取每个模板需要替换的参数
            orginParamList = econtractTemplateParamAdvancedService.queryEcontractTemplateParamAdvancedByMap(queryOriginParam);
            
            Map<String,String> searchMap = new HashMap<String,String>();
            searchMap.put("orderId", templateName.split(",")[1]);
            WorkorderDetail workOrderDeatil = workorderDetailService.findWorkorderDetailByMap(searchMap);
            String json = workOrderDeatil.getProductParam();
            String jsonStr = json.replaceAll("\n", "").replaceAll("\"null\"", "\"\"").replaceAll(":null,", ":\"\",").replaceAll(" \"", "\"");
            rsMap =  new HashMap<String,Object>();
            Map<String, Object> res = getGoodJsonMap(json, jsonStr);
            String xpath="";
            for(EcontractTemplateParamAdvanced paramAdvancde:orginParamList){
                xpath = paramAdvancde.getMethodParam();
                if(res.get(paramAdvancde.getFieldName())==null){
                    //新添加一个实现方式,是先判断是否满足前提条件,如果满足再查询数据,不满足就直接返回/
                    boolean judgeSuccess = false;//判断前提条件是否成立,false-不成立,true-成立
                    if(!StringUtils.isEmpty(xpath)&&xpath.indexOf("@&@")!=-1 || !StringUtils.isEmpty(xpath)&&xpath.indexOf("@&&@")!=-1){//存在这个符号,表示需要判断前提条件,@&@,前提条件,需要取的值的字段,单位
//                        String[] methodParamArray = xpath.split(",");
                        String[] methodParamArray = null;
                        if(!StringUtils.isEmpty(xpath)&&xpath.indexOf("@&&@")!=-1){//@&&@,前提条件中存在特殊符号
                            methodParamArray = xpath.split(";");
                        }else{
                            methodParamArray = xpath.split(",");
                        }
                        if(getXpathRes(json,methodParamArray[1])){
                            judgeSuccess = true;//需要判断前提条件
                        }else{
                            String unit = methodParamArray[methodParamArray.length-1];
                            if("null".equals(unit)){//没有单位,在最后是单位
                                rsMap.put(paramAdvancde.getFieldName(),"/");
                            }else if("instalmentsUnitToShow".equals(unit)){//分期付款特殊处理
                                rsMap.put(paramAdvancde.getFieldName(),getInstalmentsUnit(methodParamArray));
                            }else if("hasNotUnit".equals(unit)){//针对单笔最高和单笔最低
                                rsMap.put(paramAdvancde.getFieldName(),"");
                            }else{//有单位
                                rsMap.put(paramAdvancde.getFieldName(),"/"+unit);
                            }
                        }
                    }else{//不需要判断前提条件
                        judgeSuccess = true;
                    }
                    // 此xpath表达式是用来做逻辑判断的
                    if(!StringUtils.isEmpty(xpath) && xpath.indexOf("=")!=-1 && judgeSuccess && xpath.indexOf("@&@")==-1 && xpath.indexOf("@&&@")==-1){//有=号并且不存在@&@,因为前提条件中会有=号
                        //快易花商户合同里不再是黑白框  应该是√和X   订单中各期商户补贴=0或空值时,为X,费率为/;  非空时,为√,费率取对应的值
                        if(xpath.indexOf("xx=xx")!=-1){//快易花中需要用替换的
                            if(getXpathRes(json,xpath)){
                                rsMap.put(paramAdvancde.getFieldName(),"√");
                            }else{
                                rsMap.put(paramAdvancde.getFieldName(),"×");
                            }
                        }else{//其他合同还是打■或□,快易花合同中部分也需要用■或□
                            if(getXpathRes(json,xpath)){
                                rsMap.put(paramAdvancde.getFieldName(),"■");
                            }else{
                                rsMap.put(paramAdvancde.getFieldName(),"□");
                            }
                        }
                    }else if(!StringUtils.isEmpty(xpath)&& (xpath.indexOf("=")==-1 || xpath.indexOf("@&@")!=-1 || xpath.indexOf("@&&@")!=-1)&&judgeSuccess){//没有=号或者有@&@符号的规则也需要走以下逻辑
                        //如果call_method为空,则直接利用xpath进行取值替换
                        String str =getXpathValue(json,paramAdvancde.getMethodParam());
                        if(StringUtils.isEmpty(paramAdvancde.getCallMethod())){
                            rsMap.put(paramAdvancde.getFieldName(),str);
                        }else{
                            // 用来判断机具类型的,固定POS、移动POS、快刷、POS附件
//                            JSONObject obj = (JSONObject) JSONSerializer.toJSON(jsonStr);
                            JSONObject obj = getGoodJson(json, jsonStr);
                            JSONArray productListJsonArray = obj.getJSONArray("productList");
                            JSONArray PriSinBillCustomDataStr=null;
                            JSONArray PubSinBankCustomDataStr=null;
                            JSONArray PriBatchBankCustomDataStr=null;
                            JSONArray PubBatchBankCustomDataStr=null;
                            if("dspayfinancialupdatewordfir.docx".equals(templateName.split(",")[0])&&productListJsonArray.size()>0){
                                    JSONObject job = productListJsonArray.getJSONObject(0);  // 遍历 jsonarray 数组,把每一个对象转成 json 对象
                                    if(job.containsKey("PriSinBillCustomDataStr")&&job.getString("PriSinBillCustomDataStr")!=null&&xpath.indexOf("PriSinBillCustomDataStr")>-1){
                                         String PriBill =job.get("PriSinBillCustomDataStr").toString()==null?"":String.valueOf(job.get("PriSinBillCustomDataStr"));
                                         PriSinBillCustomDataStr = JSONArray.fromObject(PriBill);
                                    }else if(job.containsKey("PubSinBankCustomDataStr")&&job.getString("PubSinBankCustomDataStr")!=null&&xpath.indexOf("PubSinBankCustomDataStr")>-1){
                                         String PubBank =job.get("PubSinBankCustomDataStr").toString()==null?"":String.valueOf(job.get("PubSinBankCustomDataStr"));
                                         PubSinBankCustomDataStr = JSONArray.fromObject(PubBank);
                                    }else if(job.containsKey("PriBatchBankCustomDataStr")&&job.getString("PriBatchBankCustomDataStr")!=null&&xpath.indexOf("PriBatchBankCustomDataStr")>-1){
                                         String PriBatch =job.get("PriBatchBankCustomDataStr").toString()==null?"":String.valueOf(job.get("PriBatchBankCustomDataStr"));
                                         PriBatchBankCustomDataStr = JSONArray.fromObject(PriBatch);
                                    }else if(job.containsKey("PubBatchBankCustomDataStr")&&job.getString("PubBatchBankCustomDataStr")!=null&&xpath.indexOf("PubBatchBankCustomDataStr")>-1){
                                         String PubBatch =job.get("PubBatchBankCustomDataStr").toString()==null?"":String.valueOf(job.get("PubBatchBankCustomDataStr"));
                                         PubBatchBankCustomDataStr = JSONArray.fromObject(PubBatch);
                                    }
                                }
                            JSONArray terminalArray =new JSONArray();
                            JSONObject merchantFinanceObject = new JSONObject();//只有主协议需要这个
                            String checkTemplateNameValue = checkTemplateName(templateName);
                            // 如果产品涉及到终端直接去terminobjects中取值
                            if("1".equals(checkTemplateNameValue)){//去terminobjects中取值
                                JSONObject terminalObject = (JSONObject)productListJsonArray.get(0);
                                if((JSONArray)terminalObject.get("terminalObjects")!= null){//防止空指针
                                    terminalArray =(JSONArray)terminalObject.get("terminalObjects");
                                }
                            /*}
                            // 非终端相关的直接去productList中取值
                            else{
                                terminalArray=productListJsonArray;*/
                            }else if("2".equals(checkTemplateNameValue)){//去merchantFinance取值
                                if(obj.containsKey("merchantFinance")){
                                    merchantFinanceObject = obj.getJSONObject("merchantFinance");//主协议的时候需要用到
                                }
                            }    
                            if(productListJsonArray==null){
                                rsMap.put(paramAdvancde.getFieldName(),"");
                            }else{
                                String methodParam =paramAdvancde.getMethodParam();
//                                String[] methodParamArray = methodParam.split(",");
                                String[] methodParamArray = null;
                                if(!StringUtils.isEmpty(xpath)&&xpath.indexOf("@&&@")!=-1){//@&&@,前提条件中存在特殊符号
                                    methodParamArray = methodParam.split(";");
                                }else{
                                    methodParamArray = methodParam.split(",");//tina623
                                }
                                Object[] args = null;
                                if("1".equals(checkTemplateNameValue)){//如果产品涉及到终端直接去terminobjects中取值
                                    if(paramAdvancde.getCallMethod().startsWith("get")){
                                        args = new Object[methodParamArray.length+2];
                                        args[0]=productListJsonArray;
                                        args[1]=terminalArray;//主协议的时候,merchantFinance取的arraylist封装在这里
                                        for(int i=2;i<methodParamArray.length+2;i++){
                                            args[i]=methodParamArray[i-2];
                                        }
                                    }else if(paramAdvancde.getCallMethod().startsWith("set")){
                                        args = new Object[methodParamArray.length+1];
                                        args[0]=templateName.split(",")[1];
                                        for(int i=1;i<methodParamArray.length+1;i++){
                                            args[i]=methodParamArray[i-1];
                                        }
                                    }
                                }else if("2".equals(checkTemplateNameValue)){//主协议---主协议的时候,merchantFinance取的arraylist封装在这里
                                    if(paramAdvancde.getCallMethod().startsWith("get")){
                                        args = new Object[methodParamArray.length+2];
                                        args[0]=productListJsonArray;
                                        args[1]=merchantFinanceObject;//主协议的时候,merchantFinance取的arraylist封装在这里
                                        for(int i=2;i<methodParamArray.length+2;i++){
                                            args[i]=methodParamArray[i-2];
                                        }
                                    }else if(paramAdvancde.getCallMethod().startsWith("set")){
                                        args = new Object[methodParamArray.length+1];
                                        args[0]=templateName.split(",")[1];
                                        for(int i=1;i<methodParamArray.length+1;i++){
                                            args[i]=methodParamArray[i-1];
                                        }
                                    }
                                }else{
                                    args = new Object[methodParamArray.length+1];
                                    // 约定取值方法以get起始的话
                                    if(paramAdvancde.getCallMethod().startsWith("get")){
                                        args[0]=productListJsonArray;
                                    }else if(paramAdvancde.getCallMethod().startsWith("set")){
                                        args[0]=templateName.split(",")[1];
                                    }else if("dspayfinancialupdatewordfir.docx".equals(templateName.split(",")[0])&&paramAdvancde.getCallMethod().startsWith("twoGet")){
                                        if(xpath.indexOf("PriSinBillCustomDataStr")>-1){
                                            args[0]=PriSinBillCustomDataStr;
                                        }else if(xpath.indexOf("PubSinBankCustomDataStr")>-1){
                                            args[0]=PubSinBankCustomDataStr;
                                        }else if(xpath.indexOf("PriBatchBankCustomDataStr")>-1){
                                            args[0]=PriBatchBankCustomDataStr;
                                        }else if(xpath.indexOf("PubBatchBankCustomDataStr")>-1){
                                            args[0]=PubBatchBankCustomDataStr;
                                        }
                                    }
                                    for(int i=1;i<methodParamArray.length+1;i++){
                                        args[i]=methodParamArray[i-1];
                                    }
                                }
                                Class[] argsClass = new Class[args.length];
                                 for (int i = 0, j = args.length; i < j; i++) { 
                                     if(args[i]!=null){//避免空指针
                                         argsClass[i] = args[i].getClass();
                                     }
                                 }
                                try{
                                    Method method = crmContractUtil.getClass().getMethod(paramAdvancde.getCallMethod(),argsClass);
                                    rsMap.put(paramAdvancde.getFieldName(),method.invoke(crmContractUtil, args));
                                }catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
                else{
                    if(res.get(paramAdvancde.getFieldName())!=null && !StringUtils.isEmpty(res.get(paramAdvancde.getFieldName()).toString())){
                        rsMap.put(paramAdvancde.getFieldName(), res.get(paramAdvancde.getFieldName()));
                    }else{
                        rsMap.put(paramAdvancde.getFieldName(), "/");//如果获取的值为空,自动赋值/
                    }
                }
            }
            rsMap.put("templateName", templateName.split(",")[0]);
            rsMap = converMap(rsMap,contractNum,merchantCode,isMainFlag,res);//封装一些需要计算的数据
            aTemplateParamList.add(rsMap);
        }
        log.info("获取模板原始参数成功..aTemplateParamList===="+aTemplateParamList.toString()+"===========");
        return aTemplateParamList;
    }

@SuppressWarnings("finally")
    private String getXpathValue(String json,String xpathRule){
        String xpathValue = "/";
        try {
            JSONObject obj = getGoodJson(json, json.replaceAll("\n", "").replaceAll("\"null\"", "\"\"").replaceAll(":null,", ":\"\",").replaceAll(" \"", "\""));
            XMLSerializer serializer = new XMLSerializer();
            String xml = serializer.write(obj,"UTF-8");  
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            DocumentBuilder db;
            db = dbf.newDocumentBuilder();
            StringReader stringReader = new StringReader(xml);
            InputSource inputSource = new InputSource(stringReader);
            Document doc;
            doc = db.parse(inputSource);
            XPathFactory factory = XPathFactory.newInstance();
            XPath  xpath = factory.newXPath();
            Node node     = (Node)xpath.evaluate(xpathRule, doc,XPathConstants.NODE);
            if(node==null){
                return "/";
            }
            else{
                if(StringUtils.isEmpty(node.getTextContent())){
                    return "/";
                }else{
                    xpathValue = node.getTextContent();
                    return node.getTextContent();
                }
            }
        } catch (Exception e) {
            log.info("合同解析生成XML报错,xpathRule==="+xpathRule);
            return "/";
        }finally{
            return xpathValue;
        }
//        return "/";
    }

划红线的是和一开始的是不一样的,这里是获取json转化过来的xml的文档的node节点的值的。

isTrue = (Boolean) xpath.evaluate(xpathRule, doc,XPathConstants.BOOLEAN);
是通过xpath判断
xpathRule有没有在经过封装的xml文件的document里面的。

orginParamList = econtractTemplateParamAdvancedService.queryEcontractTemplateParamAdvancedByMap(queryOriginParam);
--根据模板名称获取

res里面装的是json转化成的map数据,根据数据库查出来的key值,去取map中的value值。并全部放在map中来。
根据数据库中参数的设置来看取值的逻辑


取值逻辑1:


callmethod 空 methodparam 空
则什么都不往map中放


取值逻辑2:


callmethod 空 methodparam 有值:比如//merchantName
它的取值逻辑主要也是用到了上面的xpath的取值逻辑。
则去json转化的map中查找,找到数值后则放进map中来


取值逻辑3:


callmethod 空 methodparam 有值:比如//isApiPayToBank=1 or //isApiPayToBill=1 or //isBatchApiPayToBank=1
其实它和2的取值逻辑是一样的,只不过xpath的表单式不一样而已。


取值逻辑4:


callmethod 有值,方法名比如setMerchantProperty methodparam 有值:比如参数address或者IpAddress_sin_99bill/IpAddress_sin_ban/IpAddress_bat_ban 可以放值多个参数
这个一般是在json格式的数据中没有这个值,但是还要获取这个数据,通过反射找到setMerchantProperty 这个方法从数据库中其它表中来获取。
address它是参数,需要根据它往反射类中的反射方法中传递的参数。
而存在map中的key值则是word文档中的命名规则,比如input。value值则是从数据库中获取的。
则会通过反射的方法来获取数值。
可以看出来只要是input开头都是通过这个方法获取的。这个主要是为了给替换做准备的。

反射的逻辑详见

反射的一个案例分析


取值逻辑5:


假如上面的4套规则还不能解决一些问题的话,则通过代码直接来设置map的key和value值,放到map中来,比如说当前的时间等等。


rsMap.put(paramAdvancde.getFieldName(), res.get(paramAdvancde.getFieldName()));
最后通过得到的数据就是

[{payBankNum=/, cwmerchantContactEmail=222@qq.com, masterDay=11, masterContractNum=K18-2000-801-03, depositAccount=/, masterYear=2018, cwmerchantContactCz=/, masterMonth=2, billAccountShareAmount=/, merchantName=还有几天就要放假了呀, year=2018, telephoneormobilephone=18068334025, legalName=222, input28=名字, ddmerchantContactTelphone=18068334025, ddmerchantContactEmail=222@qq.com, bankName=/, cwmerchantContactName=名字, cwmerchantContactTelphone=18068334025, input3=广西壮族自治区贵港市, input5=3333, ddmerchantContactName=名字, input6=3333, input20=2018年 02月 11日, month=2, ddmerchantContactCz=/, merechantURL=/, input23=2019年 02月 10日, day=11, contract_num=K18-2000-801-03, templateName=dsmainfinancialword.docx, accessType=首选, bankAccount=/}, {perMinimum=, perMinimum_pri_bat_ban=, payToCompayKqAcccountRatio=/, payBankNum=/, input69=3333, perMinimum_pub_bat_99bill=, input19=/, payToCompayAcccount=□, input18=□, autoDiectPayOpenFee=/, perMaximum_pub_bat_99bill=/, masterDay=11, input13=□, masterYear=2018, masterMonth=2, holidayPayOpenFee=/, year=2018, holidayPayTechnologyFee=/, memberCode=10012401604, telephoneormobilephone=18068334025, accumulateQuota=/, groupPayCompayKqAccountRatio=/, perMinimum_pri_sin_ban=, perMaximum=/, apiZdPayOpenFee=/, KqPayXinShi=■, bankName=/, perMinimum_pri_bat_99bill=, cwmerchantContactTelphone=18068334025, perMaximum_pri_bat_99bill=/, ddmerchantContactName=名字, BankName_bat_ban_hidden=/, AccountNum_bat_ban=/, month=2, day=11, idContent=234324fds432@qq.com, contract_num=K18-2000-801-03, apiZdPayTechnologyFee=/, perMaximum_pub_bat_ban=/, cwmerchantContactEmail=222@qq.com, holidayPay=□, perMaximum_pri_sin_99bill=/, perMinimum_pub_sin_99bill=, masterContractNum=K18-2000-801-03, groupPayCompayBankAccountRatio=/, depositAccount=/, groupPayToPersonKqAccountRatio=/, cwmerchantContactCz=/, groupPayToPersonBankAccountRatio=/, merchantName=还有几天就要放假了呀, AccountName_bat_ban=/, isBatchApiPayToBank=□, perMaximum_pri_bat_ban=/, perMinimum_pri_sin_99bill=, perMaximum_pub_sin_ban=/, input28=□, ddmerchantContactEmail=222@qq.com, ddmerchantContactTelphone=18068334025, perMinimum_pub_sin_ban=, payToCompayBankAcccountRatio=/, payPersonBankAccountRatio=/, KqPayXinShiFeeRatio=0, payPersonAccountRatio=/, cwmerchantContactName=名字, input3=□, input7=□, input6=/, input9=□, perMaximum_pub_sin_99bill=/, autoDiectPay=□, input22=□, ddmerchantContactCz=/, input24=□, input26=□, perMinimum_pub_bat_ban=, bankAccount=/, templateName=dspayfinancialaddwordfir.docx, perMaximum_pri_sin_ban=/}, {telephoneormobilephone=18068334025, ddmerchantContactEmail=222@qq.com, ddmerchantContactTelphone=18068334025, bankName=/, payBankNum=/, cwmerchantContactEmail=222@qq.com, cwmerchantContactName=名字, cwmerchantContactTelphone=18068334025, masterDay=11, masterContractNum=K18-2000-801-03, ddmerchantContactName=名字, depositAccount=/, masterYear=2018, cwmerchantContactCz=/, masterMonth=2, month=2, merchantName=还有几天就要放假了呀, year=2018, ddmerchantContactCz=/, day=11, contract_num=K18-2000-801-03, templateName=quickSubjectSeal.docx, bankAccount=/}]

还有很多很多。详情请看:http://www.cnblogs.com/qingruihappy/p/8443403.html

TopTop