【发布时间】:2022-11-10 16:49:05
【问题描述】:
标签: java apache-poi docx
标签: java apache-poi docx
XWPFDocument.getAllPictures 仅提供对XWPFPictureData 的访问,它仅表示嵌入图片的二进制文件数据。这不包含文档中图片形状的元数据。
还有XWPFRun.getEmbeddedPictures 得到XWPFPicture。这是CTPicture 元素的表示,它包含图片形状的一些元数据,但不是全部。
Word 文档中的图片存储在包含内联或锚点的图形绘图中。与文本对齐的图片存储在行内。锚定在文档中某处并具有文本流的图片存储在锚点中。内联或锚点包含形状的所有元数据。
所以需要获取图片的内联或锚点。拥有这个可以得到CTNonVisualDrawingProps,这是图片的替代文本数据的表示。
直接使用apache poi 可以获得的最接近的元素是XWPFPicture。拥有那个可以尝试获取包含找到的图片的内联或锚点。
以下完整示例显示了这一点。方法org.apache.xmlbeans.XmlObject getInlineOrAnchor(XWPFRun run, XWPFPicture picture) 是从XWPFRun run 中包含的XWPFPicture picture 中获取内联或锚点。然后方法org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps getNonVisualDrawingProps(org.apache.xmlbeans.XmlObject inlineOrAnchor) 从中获取CTNonVisualDrawingProps。 CTNonVisualDrawingProps 提供 getId、getName、getTitle 和 getDescr。 getDescr 返回 Word 显示为替代文本的文本。
import java.io.FileInputStream;
import org.apache.poi.xwpf.usermodel.*;
import java.util.List;
public class WordReadAllContent {
static org.apache.xmlbeans.XmlObject getInlineOrAnchor(org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture ctPictureToFind, org.apache.xmlbeans.XmlObject inlineOrAnchor) {
String declareNameSpaces = "declare namespace pic='http://schemas.openxmlformats.org/drawingml/2006/picture'; ";
org.apache.xmlbeans.XmlObject[] selectedObjects = inlineOrAnchor.selectPath(
declareNameSpaces
+ "$this//pic:pic");
for (org.apache.xmlbeans.XmlObject selectedObject : selectedObjects) {
if (selectedObject instanceof org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture) {
org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture ctPicture = (org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture)selectedObject;
if (ctPictureToFind.equals(ctPicture)) {
// this is the inlineOrAnchor for that picture
return inlineOrAnchor;
}
}
}
return null;
}
static org.apache.xmlbeans.XmlObject getInlineOrAnchor(XWPFRun run, XWPFPicture picture) {
org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture ctPictureToFind = picture.getCTPicture();
for (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing drawing : run.getCTR().getDrawingList()) {
for (org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline inline : drawing.getInlineList()) {
org.apache.xmlbeans.XmlObject inlineOrAnchor = getInlineOrAnchor(ctPictureToFind, inline);
// if inlineOrAnchor is not null, then this is the inline for that picture
if (inlineOrAnchor != null) return inlineOrAnchor;
}
for (org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor anchor : drawing.getAnchorList()) {
org.apache.xmlbeans.XmlObject inlineOrAnchor = getInlineOrAnchor(ctPictureToFind, anchor);
// if inlineOrAnchor is not null, then this is the anchor for that picture
if (inlineOrAnchor != null) return inlineOrAnchor;
}
}
return null;
}
static org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps getNonVisualDrawingProps(org.apache.xmlbeans.XmlObject inlineOrAnchor) {
if (inlineOrAnchor == null) return null;
if (inlineOrAnchor instanceof org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline) {
org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline inline = (org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline)inlineOrAnchor;
return inline.getDocPr();
} else if (inlineOrAnchor instanceof org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor) {
org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor anchor = (org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor)inlineOrAnchor;
return anchor.getDocPr();
}
return null;
}
static String getSummary(org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps nonVisualDrawingProps) {
if (nonVisualDrawingProps == null) return "";
String summary = "Id:=" + nonVisualDrawingProps.getId();
summary += " Name:=" + nonVisualDrawingProps.getName();
summary += " Title:=" + nonVisualDrawingProps.getTitle();
summary += " Descr:=" + nonVisualDrawingProps.getDescr();
return summary;
}
static void traversePictures(XWPFRun run, List<XWPFPicture> pictures) throws Exception {
for (XWPFPicture picture : pictures) {
//System.out.println(picture);
String picturesNonVisualDrawingProps = getSummary(getNonVisualDrawingProps(getInlineOrAnchor(run, picture)));
System.out.println(picturesNonVisualDrawingProps);
XWPFPictureData pictureData = picture.getPictureData();
//System.out.println(pictureData);
}
}
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, fieldRun.getEmbeddedPictures());
} else if (runElement instanceof XWPFHyperlinkRun) {
XWPFHyperlinkRun hyperlinkRun = (XWPFHyperlinkRun)runElement;
//System.out.println(hyperlinkRun.getClass().getName());
//System.out.println(hyperlinkRun);
traversePictures(hyperlinkRun, hyperlinkRun.getEmbeddedPictures());
} else if (runElement instanceof XWPFRun) {
XWPFRun run = (XWPFRun)runElement;
//System.out.println(run.getClass().getName());
//System.out.println(run);
traversePictures(run, 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());
}
}
}
public static void main(String[] args) throws Exception {
String inFilePath = "./WordDocument.docx";
XWPFDocument document = new XWPFDocument(new FileInputStream(inFilePath));
traverseBodyElements(document.getBodyElements());
document.close();
}
}
【讨论】:
我们从XWPFPicture 的属性中找到了这个。像这样。
for (XWPFParagraph paragraph : docx.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
String description = embeddedPicture.getDescription();
// Something
}
}
}
【讨论】: