最近有一个需求,通过java读取word文档,获取里面的批注内容,批注的作者以及被批注的内容,被批注内容所在的章节数和页码数。poi提供的API都是英文的,而且针对word的操作并不是很完善,所以就自己总结了一下。之前写的有一点问题,最近又做了下优化,不过,目前还是仅支持word2007及以上版本的格式。

首先,这里使用的是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