• Html转Doc的一种方案


      公司的合同相关部分提出需求要把html转doc文本,合同模块是现成的,基于现有合同模块初步考虑了一下可以采取以下三种方案

      1.合同模块本身有合同的html展示,可以通过前端,基于html的Doc来直接生成doc文档。

      2.公司的合同html文本是基于一套自己设计的机制,把合同条款存在数据库,以组合节点做拼接成html来做html文本动态生成的,一种可行方案是把这套机制作为数据来源,基于doc相关的开放接口包来从代码生成doc文档

      3.把现在有的html文本用第三方包转化成doc,补充上缺失的信息

      公司当前采取的是第1种方案,用jQuery的wordExport生成的doc。这种doc实际的存储方式还是用html语法,如果只是需要doc文档展示用这种方案是没问题的,但是如果要解析doc内容,貌似是没法直接解析的。这也是目前需要进行转换的原因。

      如果要生成内容准确和丰富的doc,用第二种方案来做会比较好。第二种方案的缺点在于实现复杂,需要找一个第三方生成doc的包熟悉接口才能展开,而且当前合同数据存储时,内容中已经内嵌了html文本,用这种方案的话,需要再做内容过滤或者是从数据源的角度,额外规定一个适合于内容填充符合doc生成规则的数据来源。

      第三种方案的话,也是需要找第三方包来支持的。缺点在于不确定第三方包转换限制和精确程度如何。做了几个简单和有代表性的样例测试,基于docx4j来做html转doc是可行的。不过缺点在于docx4j对于源html的语法要求很严格,很多在html里面支持的可选语法在docx4j转换时就不支持。

      调试过程中统计到的语法错误至少有:

      * 属性值缺失引号,比如item_id=123这种

      * input标签缺少结束符,比如<input ... > ,并没有对于的/或</input>

           * 错误的属性,比如  甲方,这种

      数据库里面的合同条目有8400+条,一条一条调试太过于费时,所以考虑追加一步html格式化以及过滤的步骤,选取的是google的owasp-java-html-sanitizer。初步测试是可行的。

      

    相关依赖包为:

    <!-- docx4j 的pom依赖 -->
    <!-- https://mvnrepository.com/artifact/org.docx4j/docx4j -->
    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j</artifactId>
        <version>6.1.1</version>
    </dependency>
    
    <!-- owasp-java-html-sanitizer的pom依赖 -->
    <!-- https://mvnrepository.com/artifact/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer -->
    <dependency>
        <groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
        <artifactId>owasp-java-html-sanitizer</artifactId>
        <version>20181114.1</version>
    </dependency>

    规则过滤的关键代码

    /**
         * 
         * Description: 添加过滤规则<br> 
         *  
         * @author XXX <br>
         * @taskId <br>
         * @param configs
         * @return <br>
         */
        private PolicyFactory loadFilterConfigs(Map<String, List<String>> configs) {
            HtmlPolicyBuilder builder = new HtmlPolicyBuilder();
            Set<String> labelConfigs = configs.keySet();
            for (String label : labelConfigs) {
                builder.allowElements(label);//设置支持的标签
                List<String> attributes = configs.get(label);// 如果没属性要求返回空数组
                log.debug("load label:" + label + " and attributes are :" + attributes);
                if (CollectionUtils.isEmpty(attributes)) {
                    continue;
                }
                for (String attribute : attributes) {// 配置属性
                    if (StringUtil.isEmpty(attribute)) {
                        continue;
                    }
                    builder.allowAttributes(attribute).onElements(label);
                }
    
            }
            return builder.toFactory();
        }

    这里补充说明一下,owasp-java-html-sanitizer支持对于单个标签定制过滤规则:

        builder.allowElements(new ElementPolicy() {
            @Override
            public String apply(String elementName, List<String> attrs) {// 配置属性值过滤
                System.out
                        .println("filter :" + elementName + " attrs:" + attrs );
                if (attrs != null) {
                    int itemIdIndex = attrs.indexOf("item_id");
                    if (itemIdIndex < 0) {// 不包含item_id
                        return elementName;
                    }
                    String item_id = attrs.get(itemIdIndex + 1);
                    if (attrs.contains(item_id)) {// 需要过滤
                        return null;
                    }
                    return elementName;
    
                }
                return elementName;
            }
        }, label);

    我们合同生成doc有一个需求是把没有选定的checkbox不生成到doc中,我上面代码的意图是,想先收集哪些块是没有选定的,然后通过上面的规律规则把没有选定的块过滤掉。但是实际测试结果是,这种规则过滤只对当前标签单层有效,对于嵌套的子标签并不会继承。比如:

    <div item_id='123'>
           <input type='checkbox' item_id='123' /> 
           <p>test</p>
    <div>

    这种通过上面这种思路简单配置时,<p>标签的内容并不会受到item_id的影响而过滤。这与实际的需求不符合。

    当前公司基于节点的模式,做节点解析来剔除节点是很简单的,所以上面方案测试不成功就没有继续往下深入,对于内容筛选的需求就直接基于节点来处理,owasp-java-html-sanitizer只专注于做html格式化就好了。

  • 相关阅读:
    linux安装python3.6以后报错处理
    cent07设置服务开机自启
    python进程和线程中的两个锁
    针对Material主题怎么修改 phpstorm 代码编辑器的样式
    CentOS中zip工具的基本使用
    Anaconda退出Base环境
    微擎用户自动回复对应的链接、控制器、模板
    微擎应用模块中的参数设置对应的前端页面
    微擎设置借用权限
    微擎分配不同的用户具有不同应用的操作权限
  • 原文地址:https://www.cnblogs.com/ybk2018af/p/10401082.html
Copyright © 2020-2023  润新知