跨行跨列的网页表格还原成标准表格

       解析表格数据因存在跨行跨列,导致数据无法结构化。因此必须将表格还原成标准的表格。主要思想就是先恢复跨列数据,然后再恢复跨行数据。跨列数据需要根据colspan属性来复制指定次数的单元格数据到本行数据中。跨行数据需要根据rowspan属性来复制指定次数的单元格数据到多行数据中。还原过程借助map记录单元格的内容。跨行数据恢复中,由于是从第一行第一列开始,逐行逐列遍历,因此跨行数据所在列索引就是遇到的第一个空单元格所在列位置索引。下面是java代码的实现。

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
public class TableUtil {
    /**
    * 还原跨列表格为标准表格
    * @param tableHtml 表格字符串
    * @return String    返回类型 
    */
    public static String getStandardTableWithColspan(String tableHtml) {
        if (!tableHtml.toLowerCase().startsWith("<table")) {
            tableHtml = "<table>" + tableHtml + "</table>";
        }
        StringBuffer sb = new StringBuffer();
        sb.append("<table>");
        Element table = Jsoup.parse(tableHtml).getElementsByTag("table").get(0);
        Elements trs = table.getElementsByTag("tr");
        String temp = "";
        for (Element tr : trs) {
            sb.append("<tr>");
            sb.append("\r\n");
            Elements tds = tr.children();
            for (Element td : tds) {
                if (td.outerHtml().toLowerCase().contains("colspan") && StringUtils.isNotBlank(td.attr("colspan"))) {
                    int end = Integer.parseInt(td.attr("colspan"));
                    temp = td.removeAttr("colspan").toString();
                    for (int x = 0; x < end; x++) {
                        sb.append(temp);
                        sb.append("\r\n");
                    }
                } else {
                    sb.append(td.toString());
                    sb.append("\r\n");
                }
            }
            sb.append("</tr>");
            sb.append("\r\n");
        }
        sb.append("</table>");
        return sb.toString();
    }
    /**
    * 还原跨行表格为标准表格
    * @param tableHtml 表格字符串
    * @return String    返回类型 
    */
    public static String getStandardTableWithRowspan(String tableHtml) { 
        if (!tableHtml.startsWith("<table")) {
            tableHtml = "<table>" + tableHtml + "</table>";
        }
        Map<String, String> map = new HashMap<>();
        Element table = Jsoup.parse(tableHtml);
        Elements trs = table.getElementsByTag("tr");
        Element td;
        int rowspan=0;
        for (int x = 0; x < trs.size(); x++) {
            Elements tds = trs.get(x).children();
            for(int y=0;y<tds.size();y++){
                td = tds.get(y);
                if(td.hasAttr("rowspan") && StringUtils.isNotBlank(td.attr("rowspan")) && (rowspan = Integer.parseInt(td.attr("rowspan"))) > 1){
                    td.removeAttr("rowspan");
                    int indexNull = 0;
                    boolean isFind = false;
                    //查找当前行空值的地方就是该列所在的实际位置
                    for(int m=0;m<rowspan;m++){
                        if(indexNull == 0){
                            for(;!isFind && indexNull<Integer.MAX_VALUE;indexNull++){
                                if(map.get(x+","+indexNull) == null){
                                    isFind = true;
                                    break;
                                }
                            }
                        }
                        map.put((x+m)+","+indexNull, td.outerHtml());
                    }
                }else{
                    //查找当前行空值的地方就是该列所在的实际位置
                    for(int n=0;n<Integer.MAX_VALUE;n++){
                        if(map.get(x+","+n) == null){
                            map.put(x+","+n, td.outerHtml());
                            break;
                        }
                    }
                }
            }
        }
        return getStrbyMap(map);
    }
    /**
    * 将map还原成table
    * @param map 记录表格中单元格数据 key(单元格行索引,单元格列索引) value(单元格)
    * @return String    返回类型 
    */
    private static String getStrbyMap(Map<String, String> map) {
        StringBuffer sb = new StringBuffer();
        sb.append("<table>");
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            if (!map.containsKey(i + "," + 0)) {
                sb.append("</table>");
                return sb.toString();
            }
            sb.append("<tr>");
            sb.append("\r\n");
            for (int j = 0; j < Integer.MAX_VALUE; j++) {
                if (map.containsKey(i + "," + j))
                    sb.append(map.get(i + "," + j));
                    sb.append("\r\n");
                else {
                    break;
                }
            }
            sb.append("</tr>");
            sb.append("\r\n");
        }
        sb.append("</table>");
        return sb.toString();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值