【问题标题】:How to read alt text of image in word document apache.poi如何在word文档apache.poi中读取图像的替代文本
【发布时间】:2022-11-10 16:49:05
【问题描述】:

如何使用 apache.poi 读取/编辑 word 文档图像上的 alt 文本?

我试图找到正确的功能,但 XWPFPictureData 对象内部没有任何内容。

【问题讨论】:

    标签: java apache-poi docx


    【解决方案1】:

    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) 从中获取CTNonVisualDrawingPropsCTNonVisualDrawingProps 提供 getIdgetNamegetTitlegetDescrgetDescr 返回 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();
     }
    
    }
    

    【讨论】:

      【解决方案2】:

      我们从XWPFPicture 的属性中找到了这个。像这样。

      for (XWPFParagraph paragraph : docx.getParagraphs()) {
          for (XWPFRun run : paragraph.getRuns()) {
              for (XWPFPicture embeddedPicture : run.getEmbeddedPictures()) {
                  String description = embeddedPicture.getDescription();
                  // Something
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-15
        • 1970-01-01
        • 2023-03-28
        相关资源
        最近更新 更多