从HTML内容阿拉伯字符为PDF利用iText(Arabic characters from htm

2019-10-29 22:38发布

我无法在PDF一代“?”从显示HTML内容的阿拉伯字符

我能够从显示字符串变量的阿拉伯文字。 同时,我不能够从生成HTML字符串的阿拉伯文字。

我想要一套有两列,左边英语和右侧阿拉伯文字来显示PDF。

当我用下面的程序转换成PDF格式。 请帮我在这方面。

try
{
    Document document = new Document(PageSize.A4, 50, 50, 50, 50);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PdfWriter writer = PdfWriter.getInstance(document, out);
    BaseFont bf = BaseFont.createFont("C:\\arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    Font font = new Font(bf, 8);
    document.open();

    BufferedReader br = new BufferedReader(new FileReader("C:\\style.css"));
    StringBuffer fileContents = new StringBuffer();
    String line = br.readLine();
    while (line != null)
    {
        fileContents.append(line);
        line = br.readLine();
    }
    br.close();
    String styles = fileContents.toString(); //"p { font-family: Arial;}"; 

    Paragraph cirNoEn = null;
    Paragraph cirNoAr = null;

    String htmlContentEn = null;
    String htmlContentAr = null;

    PdfPCell contentEnCell = new PdfPCell();
    PdfPCell contentArCell = new PdfPCell();

    cirNoEn = new Paragraph("Circular No. (" + cirEnNo + ")", new Font(bf, 14, Font.BOLD | Font.UNDERLINE));
    cirNoAr = new Paragraph("رقم التعميم (" + cirArNo + ")", new Font(bf, 14, Font.BOLD | Font.UNDERLINE));

    htmlContentEn = “< p >< span > Dear….</ span ></ p >”;
    htmlContentAr = “< p >< span > رقم التعميم رقم التعميم </ p >< p > رقم التعميم ….</ span ></ p >”;
    for (Element e : XMLWorkerHelper.parseToElementList(htmlContentEn, styles))
    {
        for (Chunk c : e.getChunks())
        {
            c.setFont(new Font(bf));
        }
        contentEnCell.addElement(e);
    }
    for (Element e : XMLWorkerHelper.parseToElementList(htmlContentAr, styles))
    {
        for (Chunk c:e.getChunks())
        {
            c.setFont(new Font(bf));
        }
        contentArCell.addElement(e);
    }

    PdfPCell emptyCell = new PdfPCell();
    PdfPCell cirNoEnCell = new PdfPCell(cirNoEn);
    PdfPCell cirNoArCell = new PdfPCell(cirNoAr);

    cirNoEnCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    cirNoArCell.setHorizontalAlignment(Element.ALIGN_CENTER);

    emptyCell.setBorder(Rectangle.NO_BORDER);
    emptyCell.setFixedHeight(15);

    cirNoEnCell.setBorder(Rectangle.NO_BORDER);
    cirNoArCell.setBorder(Rectangle.NO_BORDER);
    contentEnCell.setBorder(Rectangle.NO_BORDER);
    contentArCell.setBorder(Rectangle.NO_BORDER);

    cirNoArCell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    contentArCell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);

    contentEnCell.setNoWrap(false);
    contentArCell.setNoWrap(false);

    PdfPTable circularInfoTable = null;

    emptyCell.setColspan(2);
    circularInfoTable = new PdfPTable(2);
    circularInfoTable.addCell(cirNoEnCell);
    circularInfoTable.addCell(cirNoArCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(contentEnCell);
    circularInfoTable.addCell(contentArCell);
    circularInfoTable.addCell(emptyCell);

    circularInfoTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
    circularInfoTable.setWidthPercentage(100);
    document.add(circularInfoTable);

    document.close();

}
catch (Exception e)
{

}

Answer 1:

请大家看看ParseHtml7和ParseHtml8例子。 他们采取与阿拉伯字符的HTML的输入和他们创建一个具有相同阿拉伯文​​文本PDF:

我们看一下代码之前,请允许我解释说,这不是在源代码中使用非ASCII字符是一个好主意。 例如:没有这样做:

 htmlContentAr = “<p><span> رقم التعميم رقم التعميم</p><p>رقم التعميم ….</span></p>”;

你永远不知道如何包含这些字形的Java文件将被保存。 如果它不为UTF-8储存,人物最终可能看起来有点像完全不同。 版本控制系统,已知有非ASCII字符的问题,甚至编译器可以得到的编码是错误的。 如果你真的想保存的硬编码String值,在你的代码,使用Unicode符号。 你的问题的部分原因是编码问题,你可以阅读更多关于此这里: 无法获得捷克字符,而生成PDF

在屏幕截图中示出的实施例中,我使用UTF-8编码保存下列文件:

这是什么,你会在文件中找到arabic.html

<html>
<body style="font-family: Noto Naskh Arabic">
<p>رقم التعميم رقم التعميم</p>
<p>رقم التعميم</p>
</body>
</html>

这是什么,你会在文件中找到arabic2.html

<html>
<body style="font-family: Noto Naskh Arabic">
<table>
<tr>
<td dir="rtl">رقم التعميم رقم التعميم</td>
<td dir="rtl">رقم التعميم</td>
</tr>
</table>
</body>
</html>

你的问题的第二部分涉及的字体。 您使用的是知道如何绘制阿拉伯语字形的字体是很重要的。 这是很难相信,你有arial.ttf在你的根右C:驱动器。 这不是一个好主意。 我希望你用C:/windows/fonts/arialuni.ttf这当然知道阿拉伯语字形。

选择字体是不够的。 你的HTML需要知道要使用的字体系列。 因为大部分的文档中的示例使用宋体,我决定用一个能登字体。 我通过阅读这个问题,发现这些字体: 使用能登字体或来源汉斯时iText的PDF没有显示中国的文字 。 我真的很喜欢这些字体,因为它们很不错,(几乎)每一种语言的支持。 例如,我使用NotoNaskhArabic-Regular.ttf这意味着我需要定义像这样的字体FAMILIE:

style="font-family: Noto Naskh Arabic"

我定义我的XML的body标签的样式,很明显,你可以选择在哪里把它定义:在外部CSS文件中的样式部分<head>在水平<td>标签,。 ..这选择完全是你的,但你必须确定哪些地方要使用的字体。

当然:当XML工人遇到font-family: Noto Naskh Arabic ,iText的不知道在哪里可以找到相应的NotoNaskhArabic-Regular.ttf除非我们注册该字体。 我们能做到这一点,通过创建的实例FontProvider接口。 我选择使用XMLWorkerFontProvider ,但你可以自由地写自己的FontProvider实现:

XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");

还有一个障碍采取:阿拉伯语是从右到左书写。 我看到你要定义在水平的运行方向PdfPCell和你的HTML内容添加到使用这种细胞ElementList 。 这就是为什么我第一次写类似的例子,命名ParseHtml7 :

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    // HTML
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    // Pipelines
    ElementList elements = new ElementList();
    ElementHandlerPipeline pdf = new ElementHandlerPipeline(elements, null);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));

    PdfPTable table = new PdfPTable(1);
    PdfPCell cell = new PdfPCell();
    cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    for (Element e : elements) {
        cell.addElement(e);
    }
    table.addCell(cell);
    document.add(table);
    // step 5
    document.close();
}

有一个在HTML中没有表,但我们创造我们自己PdfPTable ,我们从HTML内容添加到PdfPCell与运行方向LTR,我们添加此单元格表,该表的文档。

也许这就是你的实际需要,但为什么你会在这样一个令人费解的方式做到这一点? 如果你需要一个表,你为什么不创建HTML该表,并定义一些细胞是RTL是这样的:

<td dir="rtl">...</td>

这样一来,您不必创建一个ElementList ,你可以解析HTML到PDF作为在完成ParseHtml8例如:

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

    // Pipelines
    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));;
    // step 5
    document.close();
}

有一个在这个例子中需要更少的代码,当你想改变布局,这是足以改变HTML。 你不需要改变你的Java代码。

再举一个例子:在ParseHtml9 ,我创建的一列(“阿拉伯的劳伦斯”)的英文名称和其他列的阿拉伯语翻译(“لورانسالعرب”)的表。 因为我需要英语和阿拉伯语不同的字体,我定义的字体<td>级别:

<table>
<tr>
<td>Lawrence of Arabia</td>
<td dir="rtl" style="font-family: Noto Naskh Arabic">لورانس العرب</td>
</tr>
</table>

对于第一列,默认字体使用,并从左边写向右不需要特殊的设置。 对于第二个柱,予限定阿拉伯字体和予设定的运行方向"rtl"

结果如下:

这比你想在你的代码做容易得多。



文章来源: Arabic characters from html content to pdf using iText