Apache POI XWPFRun isBold не определяет жирный шрифт - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть документ в формате doxc, в котором есть жирный текст.По какой-то причине run.isBold () имеет возвращаемое значение false, хотя run it it выделена жирным шрифтом.В чем здесь проблема?

Код, который я использую для чтения файла:

XWPFDocument document = new XWPFDocument(fis);
        for(XWPFParagraph paragraphs: document.getParagraphs()){

            for(XWPFRun run: paragraphs.getRuns()){
                System.out.println(run.isBold());

                System.out.println(run.text());
        }

Содержимое файла выглядит следующим образом:

Mõisted

2.1.Немного текста

2.1.1. Пул - какой-то текст

Странно, что заголовок ( HANKELEPINGU ÜLDTINGIMUSED ) в начале файла выделен жирным шрифтом, но послечто нет ничего смелого.

1 Ответ

0 голосов
/ 04 февраля 2019

После того как я проверил ваш файл test.docx, я могу сказать вам следующее:

Текст "Üldosa" и "Mõisted" не выделен жирным шрифтом, потому что они были отформатированы жирным шрифтом, а потому, что весь абзац выполнен в стиле "Заголовок 2" .И текст «Pooled» также не отформатирован жирным шрифтом, но применяется специальный стиль символов «Paks».Итак, кто-то широко использовал Word Styles .Совсем неплохо.Так же, как HTML лучше форматировать с использованием таблиц стилей CSS, а не напрямую, в Word также предпочтительнее использовать стиль.Но, конечно же, проблемы при разборе те же.Без дополнительного разбора таблиц стилей невозможно определить, каким образом будет представлен текст.К сожалению, apache poi до сих пор мало заботится о стилях.

Как можно прийти к такому пониманию?Файл *.docx - это просто архив ZIP.Таким образом, мы можем разархивировать его и найдем:

/word/document.xml:

<w:r ...>
 <w:rPr>
  ...
  <w:b/>
  ...
 </w:rPr>
 <w:t>HANKELEPINGU ÜLDTINGIMUSED</w:t>
</w:r>

Это текстовый прогон, отформатированный жирным шрифтом напрямую.

Но

<w:p ...>
 <w:pPr>
  <w:pStyle w:val="Heading2"/>
  <w:numPr><w:ilvl w:val="0"/><w:numId w:val="2"/></w:numPr> 
  ...
 </w:pPr>
 <w:r ...>
  <w:t>Üldosa</w:t>
 </w:r>
</w:p>

это абзац со стилем "Заголовок2", который автоматически нумеруется.

Так почему же этот текст выделен жирным шрифтом?В /word/styles.xml мы находим:

<w:style w:type="paragraph" w:styleId="Heading2">
 <w:name w:val="heading 2"/>
 <w:basedOn w:val="Normal"/>
 ...
 <w:link w:val="Heading2Char"/>
 ...
</w:style>

Это стиль абзаца "Heading2", который ссылается на стиль символа "Heading2Char".

<w:style w:type="character" w:customStyle="1" w:styleId="Heading2Char">
 <w:name w:val="Heading 2 Char"/>
 ...
 <w:link w:val="Heading2"/>
 ...
 <w:rPr>
  ...
  <w:b/>
  ...
 </w:rPr>
</w:style>

Это стиль символа "Heading2Char", который выделен жирным шрифтом.

Чтобы ответить на вопрос, как выполнить это, используя apache poi, необходимо знать, что apache poi XWPF основывается на org.openxmlformats.schemas.wordprocessingml.x2006.main.* классах, которые происходят от ooxml-schemas.*.jar.Поэтому нам нужна информация об этом.К сожалению, не существует общедоступной документации API.Поэтому нам нужно скачать исходники и сделать javadoc себя.

Так что же делать дальше?Перебираем абзацы и выполняем, как вы уже сделали.Но дополнительно для каждого абзаца попробуйте получить стиль для этого абзаца.Если он есть, найдите его и стиль его персонажа и проверьте, какие настройки он предоставляет.Также для каждого запуска попробуйте получить стиль персонажа для этого запуска.Если он есть, найдите его и проверьте, какие настройки он предоставляет.

Следующий код делает это, но только для того, чтобы проверить, обеспечивает ли стиль полужирную настройку.Так что это на самом деле не завершено, и сделать его полным будет действительно очень дорого.

import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

public class ReadWordHavingStyles {

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

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

  XWPFStyles styles = document.getStyles();
  XWPFStyle style = null;
  boolean isPBold = false;
  boolean isRBold = false;
  String boldReasonP = "";
  String boldReasonR = "";
  CTRPr cTRPr = null;

  for(XWPFParagraph paragraph : document.getParagraphs()) {
   isPBold = false;
   boldReasonP = "";
   String pStyleId = paragraph.getStyleID();
   if (pStyleId != null) {
    style = styles.getStyle(pStyleId);
    if (style != null) {
     String linkStyleId = style.getLinkStyleID();
     style = styles.getStyle(linkStyleId);
     if (style != null) {
      cTRPr = style.getCTStyle().getRPr();
      if (cTRPr != null) {
       if (!cTRPr.isSetB()) {
        isPBold = false;
       } else {
        STOnOff.Enum val = cTRPr.getB().getVal();
        isPBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
       }
      }
      boldReasonP = " whole P is " + ((isPBold)?"":"not ") + "bold because of style " + linkStyleId;
     }
    }
   }

   if (!isPBold) boldReasonP = " P is not bold";

   for(XWPFRun run : paragraph.getRuns()){
    isRBold = isPBold;
    boldReasonR = "";
    cTRPr = run.getCTR().getRPr();
    if (cTRPr != null) {
     CTString rStyle = cTRPr.getRStyle();
     if (rStyle != null) {
      String rStyleId = rStyle.getVal();
      style = styles.getStyle(rStyleId);
      if (style != null) {
       cTRPr = style.getCTStyle().getRPr();
       if (cTRPr != null) {
        if (!cTRPr.isSetB()) {
         isRBold = false;
        } else {
         STOnOff.Enum val = cTRPr.getB().getVal();
         isRBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
        }      
       }
       boldReasonR = " run is " + ((isRBold)?"":"not ") + "bold because of style " + rStyleId;
      }
     }
    }

    if (!isRBold) boldReasonR = " run is not bold";

    cTRPr = run.getCTR().getRPr();
    if (cTRPr != null) {
     if (cTRPr.isSetB()) {
      STOnOff.Enum val = cTRPr.getB().getVal();
      isRBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
      boldReasonR = " run is " + ((isRBold)?"":"not ") + "bold because of direct formatting";
     }      
    }

    System.out.println(run.text() + " isBold:" + isRBold + ":" + boldReasonP + boldReasonR);

   }
  }

  document.close();
 }
}
...