我有一个非常简单的问题让我发疯。基本上我想通过POI / DOCX4J库提取docx段结构和文档大纲。我使用POI paragraph.getLvl()方法对普通的doc文档执行了相同的任务。有没有办法用docx获得相同的结果?如何重新构建docx的整个TOC结构?
我以这种方式解决了:
Map headingMap = new HashMap();
headingMap.put("heading 1", 1);
headingMap.put("heading 2", 2);
headingMap.put("heading 3", 3);
headingMap.put("heading 4", 4);
headingMap.put("heading 5", 5);
headingMap.put("heading 6", 6);
headingMap.put("heading 7", 7);
headingMap.put("heading 8", 8);
headingMap.put("heading 9", 9);
Iterator<XWPFParagraph> iterator = docx.getParagraphsIterator();
Styles styles = getStyle(completePath);
while(iterator.hasNext()){
XWPFParagraph p = iterator.next();
if( p != null && p.getStyleID() != null){
for (Style s : styles.getStyle()){
if (p.getStyleID().equals(s.getStyleId()) && headingMap.containsKey(s.getName().getVal())){
StringBuffer text = new StringBuffer();
for(XWPFRun run : p.getRuns()) {
text.append(run.toString());
}
}
}
}
}
答案 0 :(得分:2)
大纲级别可以直接在段落或样式层次结构中设置,因此您真正的挑战是导航样式层次结构以获取它。
直接在其上设置大纲级别的段落将如下所示:
<w:p>
<w:pPr>
<w:outlineLvl w:val="2"/>
</w:pPr>
假设段对象p在docx4j中,它将是p.getPPr()。getOutlineLvl
如果在某些样式上定义了级别,例如:
<w:style w:type="paragraph" w:styleId="Heading2">
<w:name w:val="heading 2"/>
<w:basedOn w:val="Normal"/>
<w:pPr>
<w:outlineLvl w:val="1"/>
</w:pPr>
你可以使用类似的东西来获得它(忽略它可能基于它的任何样式):
private int getOutlineLvl(Style s) {
// Heading 1 is lvl 0
// There are 9 levels, so 9 will be lvl 8
// So return 9 for normal text
if (s==null
|| s.getPPr()==null) return 9;
OutlineLvl outlineLvl = s.getPPr().getOutlineLvl();
if (outlineLvl==null) return 9;
return outlineLvl.getVal().intValue();
}
在这种情况下,段落的pPr将包含以下内容:
<w:pStyle w:val="Heading2"/>
您可以从那里获得样式名称,然后需要在样式部分中查找它。看看docx4j源代码,看看如何做到这一点。
您需要知道的另一件事是如何迭代这些段落。假设你对任何内部表都不感兴趣,你可以在mdp.getContent()上使用for循环,其中mdp是主文档部分。有关详情,请参阅docx4j cheat sheet。