当前位置: 首页 > 知识库问答 >
问题:

如何在使用Apache POI阅读Word文档时获得脚注超链接?

巢安澜
2023-03-14

我正在使用ApachePOI将Word文档转换为HTML。我有一个Word文档,其中有一个脚注,其中包括一个外部超链接。我无法获取该超链接的超链接URL。这是我的代码:

List<CTHyperlink> links = paragraph.getCTP().getHyperlinkList();
log.debug("Count of hyperlinks="+links.size());
for (CTHyperlink ctHyperlink : links) {
   String rId = ctHyperlink.getId();
   log.debug("rid="+rId);
   XWPFHyperlink link = document.getHyperlinkByID(rId);
   if(link!=null) {
      log.debug("link not NULL");
   }else {
      log.debug("link is NULL");
   }
}

从上面的代码中,我看到在我的例子中,超链接的数量是2。我将rId正确地命名为“rId1”和“rId2”,但链接总是为空。

在OOXML中,我看到文档中的超链接存储在包名“/word/_rels/document.xml.rels”中,而脚注中的超链接存储在包名“/word/_rels/footnotes.xml.rels”中。可能这就是为什么我的链接变量是空的。但我不确定如何从脚注关系包中获取超链接元素。

共有1个答案

卞博简
2023-03-14

你说得对。如果代码片段中的段落位于XWPFAbstractFootnoteEndnote中,则它位于包部件/word/footnotes中。xml/word/endnotes。xml而不是在/word/document中。xml。和XWPFDocument。getHyperlinkByID仅获取存储在/word/document中的超链接。xml

解决方案取决于代码片段中的段落的来源。您没有显示这一点。

但最简单的解决方案是从XWPFParagraph获取XWPFHyperlinkRun,然后从XWPFHyperlinkRun获取XWPFHyperlink。如果XWPFHyperlinkRun的父包部分不是XWPFDocument,则必须使用底层的PackageRelationship来完成,因为直到现在为止,只有XWPFDocument才存在超链接列表。

在ApachePOI中,无法按word文档(docx)的顺序读取所有内容时,我展示了如何遍历word文档的一个基本示例。我现在扩展了这段代码,以遍历脚注和尾注以及页眉和页脚,并处理找到的XWPFHyperlinkRuns。

示例:

import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.apache.poi.openxml4j.opc.PackageRelationship;

import java.util.List;

public class WordTraverseAll {
    
 static void traversePictures(List<XWPFPicture> pictures) throws Exception {
  for (XWPFPicture picture : pictures) {
   System.out.println(picture);
   XWPFPictureData pictureData = picture.getPictureData();
   System.out.println(pictureData);
  }
 }

 static void traverseComments(XWPFRun run) throws Exception {
  CTMarkup comr = null;
  if (run.getCTR().getCommentReferenceList().size() > 0) {
   comr = run.getCTR().getCommentReferenceList().get(0);
  }
  if (comr != null) {
   XWPFComment comment = run.getDocument().getCommentByID(String.valueOf(comr.getId().intValue())); 
   System.out.println("Comment from " + comment.getAuthor() + ": " + comment.getText());   
  }
 }

 static void traverseFootnotes(XWPFRun run) throws Exception {
  CTFtnEdnRef ftn = null;
  if (run.getCTR().getFootnoteReferenceList().size() > 0) {
   ftn = run.getCTR().getFootnoteReferenceList().get(0);
  } else if (run.getCTR().getEndnoteReferenceList().size() > 0) {
   ftn = run.getCTR().getEndnoteReferenceList().get(0);   
  }
  if (ftn != null) {
   XWPFAbstractFootnoteEndnote footnote =
    ftn.getDomNode().getLocalName().equals("footnoteReference") ?
     run.getDocument().getFootnoteByID(ftn.getId().intValue()) :
     run.getDocument().getEndnoteByID(ftn.getId().intValue());
   for (XWPFParagraph paragraph : footnote.getParagraphs()) {
    traverseRunElements(paragraph.getIRuns());   
   }
  } 
 }
 
 static void traverseRunElements(List<IRunElement> runElements) throws Exception {
  for (IRunElement runElement : runElements) {
   if (runElement instanceof XWPFFieldRun) {
    XWPFFieldRun fieldRun = (XWPFFieldRun)runElement;
    //System.out.println(fieldRun.getClass().getName());
    System.out.println(fieldRun);
    traversePictures(fieldRun.getEmbeddedPictures());
   } else if (runElement instanceof XWPFHyperlinkRun) {
    XWPFHyperlinkRun hyperlinkRun = (XWPFHyperlinkRun)runElement;
    //System.out.println(hyperlinkRun.getClass().getName());
    String rId = hyperlinkRun.getHyperlinkId();
    XWPFHyperlink hyperlink = null;
    if (hyperlinkRun.getParent().getPart() instanceof XWPFAbstractFootnotesEndnotes) {
     PackageRelationship rel = hyperlinkRun.getParent().getPart().getPackagePart().getRelationships().getRelationshipByID(rId);
     hyperlink = new XWPFHyperlink(rId, rel.getTargetURI().toString()); 
    } else if (hyperlinkRun.getParent().getPart() instanceof XWPFHeaderFooter) {
     PackageRelationship rel = hyperlinkRun.getParent().getPart().getPackagePart().getRelationships().getRelationshipByID(rId);
     hyperlink = new XWPFHyperlink(rId, rel.getTargetURI().toString()); 
    } else if (hyperlinkRun.getParent().getPart() instanceof XWPFDocument) {
     hyperlink = hyperlinkRun.getDocument().getHyperlinkByID(rId);
    }
    System.out.print(hyperlinkRun);
    if (hyperlink != null) System.out.println("->" + hyperlink.getURL());
    traversePictures(hyperlinkRun.getEmbeddedPictures());
   } else if (runElement instanceof XWPFRun) {
    XWPFRun run = (XWPFRun)runElement;
    //System.out.println(run.getClass().getName());
    System.out.println(run);
    traverseFootnotes(run);
    traverseComments(run);
    traversePictures(run.getEmbeddedPictures());
   } else if (runElement instanceof XWPFSDT) {
    XWPFSDT sDT = (XWPFSDT)runElement;
    System.out.println(sDT);
    System.out.println(sDT.getContent());
    //ToDo: The SDT may have traversable content too.
   }
  }
 }

 static void traverseTableCells(List<ICell> tableICells) throws Exception {
  for (ICell tableICell : tableICells) {
   if (tableICell instanceof XWPFSDTCell) {
    XWPFSDTCell sDTCell = (XWPFSDTCell)tableICell;
    System.out.println(sDTCell);
    //ToDo: The SDTCell may have traversable content too.
   } else if (tableICell instanceof XWPFTableCell) {
    XWPFTableCell tableCell = (XWPFTableCell)tableICell;
    //System.out.println(tableCell);
    traverseBodyElements(tableCell.getBodyElements());
   }
  }
 }

 static void traverseTableRows(List<XWPFTableRow> tableRows) throws Exception {
  for (XWPFTableRow tableRow : tableRows) {
   //System.out.println(tableRow);
   traverseTableCells(tableRow.getTableICells());
  }
 }

 static void traverseBodyElements(List<IBodyElement> bodyElements) throws Exception {
  for (IBodyElement bodyElement : bodyElements) {
   if (bodyElement instanceof XWPFParagraph) {
    XWPFParagraph paragraph = (XWPFParagraph)bodyElement;
    //System.out.println(paragraph);
    traverseRunElements(paragraph.getIRuns());
   } else if (bodyElement instanceof XWPFSDT) {
    XWPFSDT sDT = (XWPFSDT)bodyElement;
    System.out.println(sDT);
    System.out.println(sDT.getContent());
    //ToDo: The SDT may have traversable content too.
   } else if (bodyElement instanceof XWPFTable) {
    XWPFTable table = (XWPFTable)bodyElement;
    //System.out.println(table);
    traverseTableRows(table.getRows());
   }
  }
 }
 
 static void traverseHeaderFooterElements(XWPFDocument document) throws Exception {
  for (XWPFHeader header : document.getHeaderList()) {
   traverseBodyElements(header.getBodyElements());
  }   
  for (XWPFFooter footer : document.getFooterList()) {
   traverseBodyElements(footer.getBodyElements());
  }   
 }
    
 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument(new FileInputStream("WordHavingHyperlinks.docx"));

  System.out.println("===== Document body elements =====");
  traverseBodyElements(document.getBodyElements());
  
  System.out.println("===== Header and footer elements =====");
  traverseHeaderFooterElements(document);
   
  document.close();

 }
}
 类似资料:
  • 在使用apache poi API阅读excel文档时,我得到了以下异常: 如果我手动从excel工作表中删除该超链接,效果很好。。。所以我的问题是,可以阅读有超链接的excel表格吗?或者是否有任何方法可以使用java代码本身删除该超链接。。谢谢

  • 我正在尝试创建一个包含多列的word文档。这样做(而不是使用表)的原因是,数据将跨越多个页面,在添加到新页面之前,我只能用列填充整个页面。 可以用ApachePOI实现吗?谢谢

  • 请问代码中的 metadatas["auth"] 是什么..

  • 问题内容: 我想使用Python创建Word文档,但是,我想尽可能多地重用现有的文档创建代码。我目前正在使用XSLT生成HTML文件,并以编程方式将其转换为PDF文件。但是,我的客户现在要求以Word(.doc)格式提供同一文档。 到目前为止,我没有太多运气找到该问题的解决方案。有谁知道可以帮助解决此问题的开源库(或 gulp 专有解决方案)? 注意:所有可能的解决方案必须在Linux上运行。我相

  • 本文向大家介绍Java 添加超链接到 Word 文档方法详解,包括了Java 添加超链接到 Word 文档方法详解的使用技巧和注意事项,需要的朋友参考一下 在Word文档中,超链接是指在特定文本或者图片中插入的能跳转到其他位置或网页的链接,它也是我们在编辑制作Word文档时广泛使用到的功能之一。今天这篇文章就将为大家演示如何使用Free Spire.Doc for Java在Word文档中添加文本

  • 我有一个Word文档(docx);我想对该文档进行更改,并将结果保存为另一个文件,保留原始文件。我有以下代码来说明我当前的问题: 我有三种方法来运行它,改变类文件底部的注释行。正如你所看到的,有三行用目标文件名创建文件输出流,写入并关闭它,还有一行只是关闭当前文档。 如果我注释掉3行并保留1行,则不会对当前文档进行任何更改(当然,也不会创建复制文档)。 如果我保留所有4行未注释,则会创建带有更改的