java - 使用 Apache POI 阅读 Word 文档时如何获取脚注超链接?
问题描述
我正在使用 Apache POI 将 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”,但链接始终为 NULL。
在 OOXML 中,我看到文档中的超链接存储在包名称“/word/_rels/document.xml.rels”中,而脚注中的超链接存储在包名称“/word/_rels/footnotes.xml”中。相对”。可能这就是我的链接变量为 NULL 的原因。但我不确定如何从脚注关系包中获取超链接元素。
解决方案
你是对的。如果paragraph
您的代码片段中的 位于 a 中,XWPFAbstractFootnoteEndnote
则它位于包部分中/word/footnotes.xml
或/word/endnotes.xml
不在/word/document.xml
. 并且XWPFDocument.getHyperlinkByID
只获取存储在/word/document.xml
.
解决方案取决于paragraph
代码片段中的来源。这个你没有显示。
但最简单的解决方案是XWPFHyperlinkRun
从 the中获取XWPFParagraph
,然后XWPFHyperlink
从 that 中获取XWPFHyperlinkRun
。如果父包部分XWPFHyperlinkRun
不是,XWPFDocument
那么这必须使用底层来完成,PackageRelationship
因为超链接列表只存在XWPFDocument
到现在。
在Apache POI 中无法按 word 文档 (docx) 的顺序读取所有内容中,我展示了一个如何遍历Word
文档的基本示例。我现在扩展此代码以遍历脚注和尾注以及页眉和页脚并处理 found XWPFHyperlinkRun
s。
例子:
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();
}
}
推荐阅读
- python - 尝试导入使用 swig 的 python 库时出现“错误的 ELF 类”错误
- node.js - 运行 npm start 并使用 npx create-react-app 创建 React 应用程序时出错
- batch-file - RPG游戏伤害问题
- javascript - 检查数组中唯一数的个数是否超过n
- python-3.x - 如何使用 python 删除 csv 文件中的这些字符?
- javascript - 减少单个数组求和切片
- r - ggmap / geosphere点子集之间的平均距离
- scala - 使用 Scala 删除 Spark 1.6 输出中的 Unicode 值
- jquery - JQuery按最小值和最大值设置选项范围
- angular - 如何修复排序,限制和跳过不适用于大量数据