1

我有一个非常简单的问题让我发疯。基本上我想通过 POI/DOCX4J 库提取 docx 段落结构和文档大纲。我使用 POI 段落.getLvl() 方法对普通文档文档执行了相同的任务。有没有办法用 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());
                    }
                }
            }
        }
    }
4

1 回答 1

2

大纲级别可以直接在段落或样式层次结构中设置,因此您真正的挑战是导航样式层次结构以获取它。

直接设置大纲级别的段落将如下所示:

        <w:p>
            <w:pPr>
                <w:outlineLvl w:val="2"/>
            </w:pPr>

假设段落对象 p,在 docx4j 中,它将是 p.getPPr().getOutlineLvl

如果在一些 style 上定义了 level,例如:

        <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 备忘单

于 2013-05-28T10:37:35.447 回答