1. 程式人生 > >Word文件轉html並提取標題

Word文件轉html並提取標題

最近做了一個功能,需要將word文件轉化成html的格式,並提取出標題生成導航。考慮到功能的複雜程度,將需要降低為對“標題1”這種格式進行提取。

docx為字尾的文件(word2007)支援XML的檔案格式,本質上是一個zip壓縮包,解壓出來就可以看到所有資訊,可能正因為如果,使用XHTMLConverter便可以得到對應的html文件,且標題元素的class屬性被標註為"X"+n(n為標題層級)。

但doc文件但相對麻煩,doc文件一般使用poi讀取,用的比較多的html轉換方式是使用poi中的WordToHtmlConverter進行轉換,這個轉換器並不會對標題進行特殊處理,將其當做普通有樣式的一個段落(Paragraph)進行處理,因此會和其他普通段落混合在一起。對此有兩種處理方法:

方案一:重寫processParagraph方法,在標黃部分加上對標題的判斷,對標題進行特殊處理,但由於WordToHtmlConverter的成員變數均宣告為private,因此我採用了另一種方案。

protected void processParagraph(HWPFDocumentCore hwpfDocument, Element parentElement, int currentTableLevel, Paragraph paragraph, String bulletText) {
    Element pElement = this.htmlDocumentFacade.createParagraph();
    parentElement.appendChild(pElement);
    StringBuilder style = new StringBuilder();
    WordToHtmlUtils.addParagraphProperties(paragraph, style);
    int charRuns = paragraph.numCharacterRuns();
    if(charRuns != 0) {
        CharacterRun characterRun = paragraph.getCharacterRun(0);
        String pFontName;
        int pFontSize;
        if(characterRun != null) {
            Triplet triplet = this.getCharacterRunTriplet(characterRun);
            pFontSize = characterRun.getFontSize() / 2;
            pFontName = triplet.fontName;
            WordToHtmlUtils.addFontFamily(pFontName, style);
            WordToHtmlUtils.addFontSize(pFontSize, style);
        } else {
            pFontSize = -1;
            pFontName = "";
        }

        this.blocksProperies.push(new WordToHtmlConverter.BlockProperies(pFontName, pFontSize));

        try {
            if(WordToHtmlUtils.isNotEmpty(bulletText)) {
                if(bulletText.endsWith("\t")) {
                    float defaultTab = 720.0F;
                    float firstLinePosition = (float)(paragraph.getIndentFromLeft() + paragraph.getFirstLineIndent() + 20);
                    float nextStop = (float)(Math.ceil((double)(firstLinePosition / 720.0F)) * 720.0D);
                    float spanMinWidth = nextStop - firstLinePosition;
                    Element span = this.htmlDocumentFacade.getDocument().createElement("span");
                    this.htmlDocumentFacade.addStyleClass(span, "s", "display: inline-block; text-indent: 0; min-width: " + spanMinWidth / 1440.0F + "in;");
                    pElement.appendChild(span);
                    Text textNode = this.htmlDocumentFacade.createText(bulletText.substring(0, bulletText.length() - 1) + '\u200b' + ' ');
                    span.appendChild(textNode);
                } else {
                    Text textNode = this.htmlDocumentFacade.createText(bulletText.substring(0, bulletText.length() - 1));
                    pElement.appendChild(textNode);
                }
            }

            this.processCharacters(hwpfDocument, currentTableLevel, paragraph, pElement);
        } finally {
            this.blocksProperies.pop();
        }

        if(style.length() > 0) {
            this.htmlDocumentFacade.addStyleClass(pElement, "p", style.toString());
        }
WordToHtmlUtils.compactSpans(pElement); } }

  方案二:在word文件中進行埋點,然後在處理過後的html文件中根據itTitleMap進行再處理

private Map<String,String> setTitleElements(HWPFDocument wordObject ){
    // 獲取樣式表
    StyleSheet styleSheet = wordObject.getStyleSheet();
    int styleTotal = wordObject.getStyleSheet().numStyles();
    // 使用map對映儲存標題資訊
    Map<String,String> idTitleMap = Maps.newHashMap();
    Range range = wordObject.getRange();
    for (int i = 0; i < range.numParagraphs(); i++) {
        // 獲取樣式資訊
        Paragraph paragraph = range.getParagraph(i);
        int styleIndex = paragraph.getStyleIndex();
        if (styleTotal > styleIndex) {
            StyleDescription styleDescription = styleSheet.getStyleDescription(styleIndex);
            String descriptionName = styleDescription.getName();
            if ( descriptionName != null  &&  descriptionName.contains(FIRST_LEVEL_TITLE_DESCRIPTION)) {
                String uuid = UUIDHelper.getUuid();
                String text = paragraph.text().replaceAll( "[\r\n]", "" );
                paragraph.replaceText( uuid, false );
                idTitleMap.put( uuid, text );
            }
        }
    }

    return idTitleMap;
}