POI docx段大纲解析

时间:2013-05-28 09:49:39

标签: java ms-word apache-poi docx docx4j

我有一个非常简单的问题让我发疯。基本上我想通过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());
                    }
                }
            }
        }
    }

1 个答案:

答案 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

相关问题