最近有一个需求,通过java读取word文档,获取里面的批注内容,批注的作者以及被批注的内容,被批注内容所在的章节数和页码数。poi提供的API都是英文的,而且针对word的操作并不是很完善,所以就自己总结了一下。
首先,这里使用的是XWPFDocument对象来读取word文档的,XWPFDocument对象提供了一个方法,可以直接获取word文档里所有的批注:
public XWPFComment[] getComments();
返回的是一个数组,里面包含所有的批注对象。
通过这种方式获取的XWPFDocument对象,其实是以一种xml格式,可以通过各种方式来验证。批注的格式为:
<w:commentRangeStart w:id="0" />
<w:t>正文文本</w:t>
</w:r>
<w:commentRangeEnd w:id="0" />
其中w:commentRangeStart表示标注的开始,w:commentRangeEnd表示标注结束了,w:t标签的值就是标注所引用的正文,w:id是标注的唯一标识。如果被引用的正文是图片的话,则标签为:
<wp:docPr id="1" name="xxx" descr="yyy.png" />
如果仅仅获取标注的信息的话,上面的内容已经足够了。下面介绍一下如何获取章节数和页码数。
前提条件是整个word的格式正确,否则得不到想要的结果。另外,需要说明的是,因为页码是根据目录来的,所有如果说某一个章节跨页的话,获取的页码可能不准确,存在偏差。
获取目录
public List<XWPFParagraph> getParagraphs();
通过上面的方法,对整个word文档逐行的进行解析,前面已经提到,解析到的对象是一种xml格式的数据,由各种标签控制着。
public CTHyperlink[] getHyperlinkArray();
如果所在的行是目录的话,会存在w:hyperlink标签,可通过上面的方法获取整个目录的内容,另外,还会存在w:anchor这样一个标签,也需要获取这个标签的值,因为这个值与下文的标题有关联,可通过这个值找到标题与目录的关联关系。
CTR[] rArray = ctHyperlink.getRArray();
for(CTR ctr : rArray) {
CTText[] tArray = ctr.getTArray();
for(CTText t : tArray) {
sb.append(t.getStringValue());
}
}
通过上面的方法可获取目录的内容。
获取正文标题
正文中的标题会有一个w:bookmarkStart标签标识,还有一个w:name标签,该标签的值与目录中的w:anchor的值一致,通过这个值,可以找到目录内容,从而得知该段落所在的章节数和页码数。
public CTBookmark[] getBookmarkStartArray();
可以通过上面的方法获取正文标题的内容。
END
上面这些方法已经足够完成需求了。可以先获取所有的标注,然后再解析word,在解析的过程中,保存章节数和页码数,最后通过标注的唯一标识id来封装最终的对象。
章节数 | 页码数 | 作者 | 批注内容 | 批注引用正文 |
1.1 | 3 | Steven_sf | 批注 | test |
关于word解析后的xml格式,里面还有很多标签可以使用,有兴趣的请自行了解。
相关源码下载