刚刚接触XWPF,之前总算对HWPF摸得比较熟了,在POI对word2007摸索的过程中却发现不少问题。网上对POI的有用资料本来也不多,对于XWPF的几乎没有,这里做一点总结:
1 解析word2007需要7个包,poi,poi-scratchpad,poi-ooxml,poi-ooxml-schemas,xmlbeans,dom4j,geronimo-stax-api,缺少的话会运行时保错,暂未发现JDK版本的冲突。
2 XWPF似乎是自成体系,没有从HWPF继承已有的一些对象,不知道是原来的架构没做好还是两种word文件格式相差太大,这对于我原来的程序需要兼容多个版本word造成不少麻烦。
3 从已有的情况看,XWPF似乎是不支持isInTable的判断,检查XWPFWordExtractor解析getText的代码,居然是解析了文本,再解析表格,狂晕,作者还没找到定位table表格位置的方法?而且表格的内容似乎不再存于paragraph中了
由于XWPF采用openxml解析xml,并把所有同类的标签都分类解析,所以导出为文字时已经无法区分顺序了,实际上在docx中是顺序存放的,但是解析后把段落和表格分开存放,同时也就丢失了两者的位置关系,在Extractor就只能分别输出了,无语的半成品阿。
4 cell中居然可以支持多个段落,但是不再试用getParagraph方法,或者说只能获取一个段落getParagraph,必须用另外的方法读取。
5 从测试用例的程序可以看出,附件(如图片)是可以读出的,超链接应该也是可以的,没有详细查看。
6 cell居然无法获得宽度,郁闷,表格的问题相当多。看看它连getText都没来得及做可知完成的多么仓促
public String getText() { //TODO return null; }
7 优势方面,理论上来说已经可以区分修订的添加或者删除内容了(虽然Extractor还是同样全部输出),但是和表格同一个德行,添加和删除的内容被分类读取出来了,同样无法判断顺序,于是Extractor按照一般、删除和插入的顺序输出文字,无语...
protected XWPFParagraph(CTP prgrph, XWPFDocument docRef) { this.paragraph = prgrph; this.document = docRef; if (!isEmpty()) { // All the runs to loop over // TODO - replace this with some sort of XPath expression // to directly find all the CTRs, in the right order ArrayList<CTR> rs = new ArrayList<CTR>(); rs.addAll(Arrays.asList(paragraph.getRArray())); for (CTSdtRun sdt : paragraph.getSdtArray()) { CTSdtContentRun run = sdt.getSdtContent(); rs.addAll(Arrays.asList(run.getRArray())); } for (CTRunTrackChange c : paragraph.getDelArray()) { rs.addAll(Arrays.asList(c.getRArray())); } for (CTRunTrackChange c : paragraph.getInsArray()) { rs.addAll(Arrays.asList(c.getRArray())); }
8 (2-5)今天发现ooxml解析还存在一个bug,没有解析下面的标签
<w:smartTag w:uri="urn:schemas-microsoft-com:office:smarttags" w:element="place"> <w:r> <w:rPr> <w:rFonts w:ascii="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:hAnsi="宋体" w:cs="宋体"/> <w:b/> <w:bCs/> <w:kern w:val="0"/> <w:szCs w:val="21"/> </w:rPr> <w:t>Para</w:t> </w:r> </w:smartTag>
smallTag的标签不知道有什么意义,是word文档自己生成的,从word中看,标签中的内容和其他文字样式上没有任何不同,但是ooxml不会解析这个标签,导致文字丢失。
目前而言,感觉XWPF完成的相当粗糙,例子很少,只有两个编辑的例子,文档则几乎没有,文档格式为xml,哪怕自己解析估计也不必POI差多少,不推荐使用。
9 宏替换标签直接把内容并入文本,导致缺少标志性标志(前缀和后缀),这样勉强替换可能误改正文,不过也没法子了。checkbox的例子,用了<w:instrText xml:space="preserve">标签,你可以看出word文档有多么繁琐。
<w:r w:rsidRPr="00E7434E"> <w:rPr> <w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/> <w:kern w:val="0"/> <w:szCs w:val="21"/> </w:rPr> <w:instrText xml:space="preserve">MACROBUTTON UncheckIt</w:instrText> </w:r> <w:r w:rsidRPr="00E7434E"> <w:rPr> <w:rFonts w:ascii="宋体" w:hAnsi="Wingdings" w:cs="宋体" w:hint="eastAsia"/> <w:kern w:val="0"/> <w:szCs w:val="20"/> </w:rPr> <w:sym w:font="Wingdings" w:char="F0FE"/> </w:r> <w:r w:rsidRPr="00E7434E"> <w:rPr> <w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/> <w:kern w:val="0"/> <w:szCs w:val="21"/> </w:rPr> <w:fldChar w:fldCharType="end"/> </w:r> <w:r w:rsidRPr="00E7434E"> <w:rPr> <w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/> <w:kern w:val="0"/> <w:szCs w:val="21"/> </w:rPr> <w:t xml:space="preserve"></w:t> </w:r> <w:r w:rsidRPr="00157D2C"> <w:rPr> <w:rFonts w:hint="eastAsia"/> </w:rPr> <w:t>固定资产</w:t> </w:r>
//*********************************************************
XWPF比较详细一点的介绍 http://hi.baidu.com/zrzx/blog/item/dde3bc31b9e248a15fdf0e36.html
费了很多功夫总算补充了POI无法定位表格位置和读取对象属性的问题,庆贺一个先。