Как получить чертежи из apache POI XWPFDocument? - PullRequest
0 голосов
/ 06 мая 2020

Я пытался получить чертежи из XWPFDocument таким способом (мой data.docx содержит только один прямоугольник и его текст).

    XWPFDocument wordDocumentObj = new XWPFDocument(new FileInputStream(new File("data.docx")));
    Iterator<IBodyElement> bodyElementIterator = wordDocumentObj.getBodyElementsIterator();

    while(bodyElementIterator.hasNext()){
        IBodyElement element = bodyElementIterator.next();
        if (element instanceof XWPFParagraph) {
             XWPFParagraph paragrapObj = (XWPFParagraph)element;
             for(IRunElement irunObj : paragrapObj.getIRuns()) {
                 XWPFRun runObj = (XWPFRun)irunObj;
                 // I read whole the API doc, I think it is the only way to get the drawings
                 System.out.println(runObj.getCTR().getDrawingList());// No element returned
                 System.out.println(runObj.getCTR().getDrawingArray());// No element returned
             }
        }
    }

Есть ли у вас идеи получить чертежи из XWPFDocument ?

Обновлено: XML содержимое XWPFRun. Я попытался извлечь текстовый файл. В каталоге / word / * нет изображения:


<xml-fragment >
   <mc:AlternateContent>
      <mc:Choice Requires="wps">
         <w:drawing>
            <wp:anchor>
               <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                  <a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
                     <wps:wsp>
                        <wps:txbx>
                           <w:txbxContent>
                              <w:p w14:paraId="2744738E" w14:textId="0811E43C" w:rsidR="00832A19" w:rsidRDefault="00832A19" w:rsidP="00832A19">
                                 <w:r>
                                    <w:t>Some text here</w:t>
                                 </w:r>
                              </w:p>
                           </w:txbxContent>
                        </wps:txbx>

                     </wps:wsp>
                  </a:graphicData>
               </a:graphic>
            </wp:anchor>
         </w:drawing>
      </mc:Choice>
      <mc:Fallback>
         <w:pict>
            <v:rect w14:anchorId="684D682E" id="Rectangle 2" o:spid="_x0000_s1026" style="" fillcolor="#4f81bd [3204]" strokecolor="#243f60 [1604]" strokeweight="2pt">
               <v:textbox>
                  <w:txbxContent>
                     <w:p w14:paraId="2744738E" w14:textId="0811E43C" w:rsidR="00832A19" w:rsidRDefault="00832A19" w:rsidP="00832A19">
                        <w:r>
                           <w:t>Some text here</w:t>
                        </w:r>
                     </w:p>
                  </w:txbxContent>
               </v:textbox>
            </v:rect>
         </w:pict>
      </mc:Fallback>
   </mc:AlternateContent>
</xml-fragment>

1 Ответ

2 голосов
/ 06 мая 2020

Ваш предоставленный XML показывает, что ваш Word документ использует альтернативное содержимое, которое было введено после публикации Office Open XML в 2007 году. Таким образом, apache poi не предоставляет методов для получения этого содержимого, поскольку он предоставляет методы только для Office Open XML по стандарту ECMA-376. Это потому, что базовый ooxml-schemas был создан только из этого ECMA-376 стандарта.

Таким образом, элементы drawing в элементах AlternateContent можно получить только с помощью методов XML (XPath)

Это может выглядеть так:

import java.io.FileInputStream;

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

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;

import java.util.List;
import java.util.ArrayList;

public class WordGetAllDrawingsFromRuns {

 private static List<CTDrawing> getAllDrawings(XWPFRun run) throws Exception {
  CTR ctR = run.getCTR();
  XmlCursor cursor = ctR.newCursor();
  cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:drawing");
  List<CTDrawing> drawings = new ArrayList<CTDrawing>();
  while (cursor.hasNextSelection()) {
   cursor.toNextSelection();
   XmlObject obj = cursor.getObject();
   CTDrawing drawing = CTDrawing.Factory.parse(obj.newInputStream());
   drawings.add(drawing);
  }
  return drawings;
 }

 public static void main(String[] args) throws Exception {

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

  for (IBodyElement bodyElement : document.getBodyElements()) {
   if (bodyElement instanceof XWPFParagraph) {
    XWPFParagraph paragraph = (XWPFParagraph) bodyElement;
    for(IRunElement runElement : paragraph.getIRuns()) {
     if (runElement instanceof XWPFRun) {
      XWPFRun run = (XWPFRun) runElement;
      List<CTDrawing> drawings = getAllDrawings(run);
      System.out.println(drawings);

     }
    }
   }
  }

  document.close();
 }
}

Но следующая проблема будет заключаться в том, как получить содержимое из элементов drawing, тогда как <wps:wsp><wps:txbx> также не является частью Office Open XML согласно стандарту ECMA-376. Так что ooxml-schemas методы CTDrawing также не могут их получить. Поэтому, если необходимо затем получить содержимое текстового поля из чертежа, это также возможно только с использованием методов XML (XPath) напрямую.

Тогда это может выглядеть так:

 private static CTTxbxContent getTextBoxContent(CTDrawing drawing) throws Exception {
  XmlCursor cursor = drawing.newCursor();
  cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent");
  List<CTTxbxContent> txbxContents = new ArrayList<CTTxbxContent>();
  while (cursor.hasNextSelection()) {
   cursor.toNextSelection();
   XmlObject obj = cursor.getObject();
   CTTxbxContent txbxContent = CTTxbxContent.Factory.parse(obj.newInputStream());
   txbxContents.add(txbxContent);
   break;
  }
  CTTxbxContent txbxContent = null;
  if (txbxContents.size() > 0) {
   txbxContent = txbxContents.get(0);
  }
  return txbxContent;
 }
...