Как установить разные стили для одного и того же абзаца - PullRequest
0 голосов
/ 19 января 2019

Я пытаюсь преобразовать HTML-текст для создания таблицы слов. Он работает довольно хорошо, и созданный файл слов корректен, за исключением стилей символов.

Это моя первая попытка использования Apache POI.

До сих пор мне удавалось обнаружить теги новой строки (
) из текстового абзаца (см. Код ниже). Но я хотел бы также проверить несколько других тегов, таких как , , и установить правильные значения прогона для каждой детали.

Например:
Это мой текст , который теперь выделен курсивом , но также выделен жирным шрифтом в зависимости от его важности

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

private static  XWPFParagraph getTableParagraph(XWPFTableCell  cell,  String text)
{   
    int fontsize= 11; 
    XWPFParagraph paragraph = cell.addParagraph();
    cell.removeParagraph(0);
    paragraph.setSpacingAfterLines(0);
    paragraph.setSpacingAfter(0);
    XWPFRun myRun1 = paragraph.createRun();
    if (text==null) text="";
    else
    {
        while (true)
        {
            int x = text.indexOf("<br>"); 
            if (x <0) break;
            String work = text.substring(0,x );
            text= text.substring(x+4);
            myRun1.setText(work);
            myRun1.addBreak();
        }
    }

    myRun1.setText(text);
    myRun1.setFontSize(fontsize);
    return paragraph;
}

1 Ответ

0 голосов
/ 20 января 2019

При преобразовании текста HTML никогда не следует переходить на HTML, используя только строковые методы.XML, а также HTML являются языками разметки.Их содержание - разметка, а не только простой текст.Разметка должна быть пройдена, чтобы получить все отдельные узлы вместе со значениями из нее.Этот процесс обхода никогда не бывает тривиальным, поэтому существуют специальные библиотеки.Глубоко внутри этих библиотек также необходимо использовать строковые методы, но они обернуты в полезные методы для обхода разметки.

Для обхода можно использовать, например, HTML jsoup .Особенно NodeTraversor с использованием NodeVisitor полезен для обхода HTML.

В моем примере создается ParagraphNodeVisitor, который реализует NodeVisitor.Этот интерфейс запрашивает метод public void head(Node node, int depth), который вызывается каждый раз, когда NodeTraversor находится в начале узла, и public void tail(Node node, int depth), который вызывается каждый раз, когда NodeTraversor находится в хвостовой части узла.В этих методах может быть реализован процесс обработки отдельных узлов.В нашем случае основная часть процесса заключается в том, нужен ли нам новый XWPFRun и какие настройки нужны для этого запуска.

Пример:

import java.io.FileOutputStream;

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

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.select.NodeVisitor;
import org.jsoup.select.NodeTraversor;

public class HTMLtoDOCX {

 private XWPFDocument document;

 public HTMLtoDOCX(String html, String docxPath) throws Exception {

  this.document = new XWPFDocument();

  XWPFParagraph paragraph = null;
  Document htmlDocument = Jsoup.parse(html);
  Elements htmlParagraphs = htmlDocument.select("p");
  for(Element htmlParagraph : htmlParagraphs) {

System.out.println(htmlParagraph);

   paragraph = document.createParagraph();
   createParagraphFromHTML(paragraph, htmlParagraph);
  }

  FileOutputStream out = new FileOutputStream(docxPath);
  document.write(out);
  out.close();
  document.close();

 }

 void createParagraphFromHTML(XWPFParagraph paragraph, Element htmlParagraph) {

  ParagraphNodeVisitor nodeVisitor = new ParagraphNodeVisitor(paragraph);
  NodeTraversor.traverse(nodeVisitor, htmlParagraph);

 }

 private class ParagraphNodeVisitor implements NodeVisitor {

  String nodeName;
  boolean needNewRun;
  boolean isItalic;
  boolean isBold;
  boolean isUnderlined;
  int fontSize;
  String fontColor;
  XWPFParagraph paragraph;
  XWPFRun run;

  ParagraphNodeVisitor(XWPFParagraph paragraph) {
   this.paragraph = paragraph;
   this.run = paragraph.createRun();
   this.nodeName = "";
   this.needNewRun = false;
   this.isItalic = false;
   this.isBold = false;
   this.isUnderlined = false;
   this.fontSize = 11;
   this.fontColor = "000000";

  }

  @Override
  public void head(Node node, int depth) {
   nodeName = node.nodeName();

System.out.println("Start "+nodeName+": " + node);

   needNewRun = false;
   if ("#text".equals(nodeName)) {
    run.setText(((TextNode)node).text​());
    needNewRun = true; //after setting the text in the run a new run is needed
   } else if ("i".equals(nodeName)) {
    isItalic = true;
   } else if ("b".equals(nodeName)) {
    isBold = true;
   } else if ("u".equals(nodeName)) {
    isUnderlined = true;
   } else if ("br".equals(nodeName)) {
    run.addBreak();
   } else if ("font".equals(nodeName)) {
    fontColor = (!"".equals(node.attr("color")))?node.attr("color").substring(1):"000000";
    fontSize = (!"".equals(node.attr("size")))?Integer.parseInt(node.attr("size")):11;
   } 
   if (needNewRun) run = paragraph.createRun();
   needNewRun = false;
   run.setItalic(isItalic);
   run.setBold(isBold);
   if (isUnderlined) run.setUnderline(UnderlinePatterns.SINGLE); else run.setUnderline(UnderlinePatterns.NONE);
   run.setColor(fontColor); run.setFontSize(fontSize);
  }

  @Override
  public void tail(Node node, int depth) {
   nodeName = node.nodeName();

System.out.println("End "+nodeName);

   if ("i".equals(nodeName)) {
    isItalic = false;
   } else if ("b".equals(nodeName)) {
    isBold = false;
   } else if ("u".equals(nodeName)) {
    isUnderlined = false;
   } else if ("font".equals(nodeName)) {
    fontColor = "000000";
    fontSize = 11;
   }
   if (needNewRun) run = paragraph.createRun();
   needNewRun = false;
   run.setItalic(isItalic);
   run.setBold(isBold);
   if (isUnderlined) run.setUnderline(UnderlinePatterns.SINGLE); else run.setUnderline(UnderlinePatterns.NONE);
   run.setColor(fontColor); run.setFontSize(fontSize);
  }
 }

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

  String html = 
   "<p><font size='32' color='#0000FF'><b>First paragraph.</font></b><br/>Just like a heading</p>"
  +"<p>This is my text <i>which now is in italic <b>but also in bold</b> depending on its <u>importance</u></i>.<br/>Now a <b><i><u>new</u></i></b> line starts <i>within <b>the same</b> paragraph</i>.</p>"
  +"<p><b>Last <u>paragraph <i>comes</u> here</b> finally</i>.</p>"
  +"<p>But yet <u><i><b>another</i></u></b> paragraph having <i><font size='22' color='#FF0000'>special <u>font</u> settings</font></i>. Now default font again.</p>";

  HTMLtoDOCX htmlToDOCX = new HTMLtoDOCX(html, "./CreateWordParagraphFromHTML.docx");

 }
}

Результат:

enter image description here

Отказ от ответственности: Это рабочий проект, показывающий принцип.Он не полностью готов и не готов для использования в продуктивной среде.

...