龙空技术网

使用poi-tl、poi-tl-ext遇到块级元素嵌套导致空白段落问题

北方有雪吗 37

前言:

现在兄弟们对“div嵌套div布局如何爬”大概比较着重,姐妹们都需要剖析一些“div嵌套div布局如何爬”的相关资讯。那么小编在网络上汇集了一些关于“div嵌套div布局如何爬””的相关内容,希望各位老铁们能喜欢,兄弟们一起来了解一下吧!

依赖包版本:

<!--poi-tl word支持--><dependency>    <groupId>com.deepoove</groupId>    <artifactId>poi-tl</artifactId>    <version>1.10.4</version></dependency><!--poi-tl html转word插件支持--><dependency>    <groupId>io.github.draco1023</groupId>    <artifactId>poi-tl-ext</artifactId>    <version>0.4.1</version></dependency>

普通情况下使用方式:

// 定义一个html渲染策略HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();Configure configure = Configure.builder()        .bind("html", htmlRenderPolicy)        .build();

word模板:

word模板

遇到问题:当html存在块级元素嵌套,如div嵌套div,则会出现空白段落问题,嵌套几层,就出现几个空白段落,这与html在web页面渲染的效果不一致。嵌套的html段落如下:

<div  class="xxx">      <div class="xxx">          <p>你好!</p>      </div>  </div>

渲染效果:

渲染结果多出了两个空白段落

原因:经过查看poi-tl-ext源码(org.ddr.poi.html.HtmlRenderContext.renderElement(Element element)),发现,当遇到【块级元素】时,会自动生成一个新的段落,虽然也存在空白段落问题的处理,但是为什么没有处理到这种情况,暂时还不清楚。

HtmlRenderContext提供的防重策略

使用markDedupe标记段落以防止块状元素嵌套产生多余的空段落

初步解决方案:利用org.ddr.poi.html.HtmlRenderContext.renderElement提供的markDedupe()和unmarkDedupe(),然后自定义div(或者其它标签)标签的渲染逻辑。

改进后的方案:

一、新增块级元素(div示例)的渲染策略:

import org.apache.commons.lang3.StringUtils;import org.ddr.poi.html.ElementRenderer;import org.ddr.poi.html.HtmlRenderContext;import org.jsoup.nodes.Element;import org.jsoup.nodes.Node;import java.util.Objects;/** * @description: div渲染 * @author: xx * @create: 2022-11-16 17:01:56 **/public class BlockRenderer implements ElementRenderer {    private static final String[] TAGS = {"div", "p"};    /**     * 开始渲染     *     * @param element HTML元素     * @param context 渲染上下文     * @return 是否继续渲染子元素     */    @Override    public boolean renderStart(Element element, HtmlRenderContext context) {        // 如果当前块级元素,存在内容        String ownText = element.ownText();        if (StringUtils.isNotBlank(ownText)) {            return true;        }        Node firstNode = element.childNode(0);        // 如果没有子元素,则返回        if (Objects.isNull(firstNode)) {            return true;        }        // 判断第一个子元素是否是块级元素        if (firstNode instanceof Element) {            Element firstChildElement = ((Element) firstNode);            if (firstChildElement.isBlock()) {                // 如果是,则当前块级元素不生成新的段落,否则会形成空白行                context.markDedupe(context.getClosestParagraph());            }        }        return true;    }    /**     * 元素渲染结束需要执行的逻辑     *     * @param element HTML元素     * @param context 渲染上下文     */    @Override    public void renderEnd(Element element, HtmlRenderContext context) {        context.unmarkDedupe();    }/*** 支持的标签*/    @Override    public String[] supportedTags() {        return TAGS;    } /**     * 是否渲染为块级元素,如果是,则创建新段落     *     */    @Override    public boolean renderAsBlock() {        return true;    }}

二、配置html的渲染策略:

import org.ddr.poi.html.ElementRenderer;import org.ddr.poi.html.HtmlRenderConfig;import org.ddr.poi.html.HtmlRenderPolicy;import java.util.ArrayList;import java.util.List;import java.util.Objects;/** * @description: html渲染策略 * @author:  * @create: 2022-11-17 09:13:37 **/public class HtmlRenderPolicyConfig {    /**     * 获取html渲染策略     *     * @return     */    public static HtmlRenderPolicy getHtmlRenderPolicy() {        HtmlRenderConfig htmlRenderConfig = new HtmlRenderConfig();        List<ElementRenderer> customRenderers = htmlRenderConfig.getCustomRenderers();        if (Objects.isNull(customRenderers)) {            customRenderers = new ArrayList<>(4);        }       // 装载自定义的标签渲染器策略        customRenderers.add(new BlockRenderer());        htmlRenderConfig.setCustomRenderers(customRenderers);        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy(htmlRenderConfig);        return htmlRenderPolicy;    }}

三、使用方式不变:

Configure configure = Configure.builder()        .bind("html", HtmlRenderPolicyConfig.getHtmlRenderPolicy())        .build();

四、效果:

调整后的渲染效果

总结:目前暂时不知道这种解决方案,有可能带来的其它影响,因为目前业务上,以及使用的测试html字符串不是太复杂,所以达不到普适性,参考时,请根据实际=情况自行处理。

标签: #div嵌套div布局如何爬 #div的多层嵌套 #java引入poi依赖包 #cssdiv嵌套 #表格嵌套表格 element