JAVA Apache POI解析docx格式的word文件并提取带样式文本

关于JAVA Apache POI读取word文档,网上资料很多,但是大多数还是仅仅提取文档中的纯文本,好一点的,也就提取所有图片,但是,word文档本身是具有样式的,这样简单粗暴的提取就会丢失字体、字号、颜色、粗体、斜体等一系列样式,也没有办法还原图片在文档流中的位置,没有办法提取出表格。

docx格式的word文件实际上是一个压缩包,通过修改后缀名为rar后可用winrar打开,里面实际上是xml文件

这是因为docx文件遵循了OfficeOpenXML规范,该规范内容很多,有兴趣的同学可以自行下载翻阅。打开上图的word文件夹

这里我们需要关注的是document.xml和numbering.xml

其中document.xml包含了文档的主要结构与主要文本内容,其形式有点像HTML语言

而numbering.xml与自动序号有关,由于非常复杂,文本暂不讨论,主要原因是自动序号实际上是在渲染时进行实时计算的,并且需要有不同的层次。

在开始使用Apache POI解析之前,我们需要了解一些关于docx文件结构的基本概念

整个文档是一个document,document的子元素为Paragraph(段落)和Table(表格)这和我们日常使用word的经验基本相符,Paragraph的子元素为Run,代表一段连续的相同样式的文本,一般来说,没有改过样式的一段纯中文或者纯英文就在一个Run内,而一旦对其中一个字改变了字号、颜色、粗细等样式,那么其本身及前后必然会被不同的Run分割。

在实际使用Apache POI中,又分为High Level和Low Level两种API,一般以XWPF作为前缀的是High Level API,以CT为前缀的是Low Level,High Level API使用更简单,比较容易理解,但是目前只有比较常见的元素有,例如XWPFParagraph、XWPFRun。Low Level API实际上是对xml文件中标签的简单封装,需要你对OfficeOpenXML规范有足够的了解,例如CTP(Paragraph)、CTR(Run)。当然,Low Level API也不一定能满足你的全部需求,这个时候你只能对着OfficeOpenXML文档自行解析XML了。High Level API可以获取到对应的Low Level API,例如,XWPFParagraph.getCTP()。

上图是High Level API的类的主要关系图,其中蓝色的是class,绿色的是interface

List<XWPFParagraph> paragraphs = document.getParagraphs();
for(XWPFParagraph paragraph:paragraphs){
    List<XWPFRun> runs= paragraph.getRuns();
    for(XWPFRun run:runs){
        List<XWPFPicture> pictures=run.getEmbeddedPictures();
        String text=run.text();
    }
}

一般来说,我们使用XWPFParagraph、XWPFRun、XWPFPicture就能满足绝大多数情况。由于图片的情况较为复杂,这里能抽取的图片是嵌入型的图片,而衬于文字上/下方的图片抽取较为复杂,本文暂不讨论。

下面就主要讲讲XWPFParagraph与XWPFRun的样式相关API

1.对齐方式

 xwpfParagraph.getAlignment().getValue()

下表仅列出常用对齐方式

返回值含义
1左对齐
2居中
3右对齐

2.字体

 run.getFontFamily()

3.字号

run.getFontSize()

4.粗体

run.isBold()

5.斜体

run.isItalic()

6.下划线

run.getUnderline().getValue()

下表仅列出常用下划线

返回值含义
1单下划线
3双下划线

7.下标

run.getVerticalAlignment().equals(STVerticalAlignRun.Enum.forInt(3))

8.上标

run.getVerticalAlignment().equals(STVerticalAlignRun.Enum.forInt(2))

9.颜色

 run.getColor()

表格抽取相对较简单,最终又回到XWPFParagraph

List<XWPFTableRow> xwpfTableRows = xwpfTable.getRows();
for (XWPFTableRow xwpfTableRow : xwpfTableRows) {
    List<XWPFTableCell> xwpfTableCells = xwpfTableRow.getTableCells();
    for (XWPFTableCell xwpfTableCell : xwpfTableCells) {
        List<XWPFParagraph> xwpfParagraphs = xwpfTableCell.getParagraphs();
    }
}

最后补充一些特殊情况,这些情况需要用到Low level API

1.oMath公式

office中公式的版本很乱,因为涉及到历史兼容原因,老版本的公式只能抽取为图片,最新版本的公式可以抽取为xml

List<CTOMath> ctoMaths = xwpfParagraph.getCTP().getOMathList();

顺带说一句,oMath可以转换为mml再转换为Latex语言

2.特殊符号

有些特殊符号是用的某种字体中的某个字符,一般使用&#x unicode进行显示

List<CTSym> ctSyms = run.getCTR().getSymList();
if (ctSyms.size() > 0) {
    String symHtml = "";
    for (CTSym ctSym : ctSyms) {
        String font = ctSym.getFont();
        byte[] chars = ctSym.getChar();
        String unicode = "";
        for (byte aChar : chars) {
            int realInt = aChar & 0xff;
            String hex = Integer.toHexString(realInt);
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
        }
        unicode += hex;
    }
}

3.着重号

run.getCTR().getRPr() != null && run.getCTR().getRPr().getEm() != null && run.getCTR().getRPr().getEm().getVal().toString().equals("dot")

 

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要使用Apache POI库生成Word文档,你可以按照以下步骤进行操作: 1. 导入所需的POI库: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 2. 编写代码来创建并编辑Word文档: ```java import org.apache.poi.xwpf.usermodel.*; import java.io.FileOutputStream; import java.io.IOException; public class WordDocumentGenerator { public static void main(String[] args) { // 创建一个新的Word文档 XWPFDocument document = new XWPFDocument(); // 创建段落 XWPFParagraph paragraph = document.createParagraph(); // 创建文本运行 XWPFRun run = paragraph.createRun(); // 设置文本内容 run.setText("这是一个生成的Word文档。"); // 添加换行符 paragraph.createRun().addBreak(); // 添加一个样式文本 XWPFRun styledRun = paragraph.createRun(); styledRun.setText("这是样式文本。"); styledRun.setBold(true); styledRun.setFontSize(14); // 保存文档 try { FileOutputStream out = new FileOutputStream("example.docx"); document.write(out); out.close(); System.out.println("生成Word文档成功!"); } catch (IOException e) { e.printStackTrace(); } } } ``` 上述代码创建了一个简单的Word文档,其中包含两个段落。第一个段落包含文本"这是一个生成的Word文档。",第二个段落包含样式文本"这是样式文本。"。最后,将文档保存为名为`example.docx`的文件。你可以根据需要添加更多的段落、表格、图片以及其他格式设置。记得根据实际情况进行异常处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值