如何从 Jaspersoft/JRXML 生成双语标记 PDF 输出?

How to produce a bilingual tagged-PDF output from Jaspersoft / JRXML?

我们正在使用 Jaspersoft iReport Designer 创建双语 PDF 输出——每个文件都包含英语和法语文本。

出于可访问性原因,我们希望在生成的 PDF 中用相应的语言标记每个文本块。请参阅 PDF19: Specifying the language for a passage or phrase with the Lang entry in PDF documents 了解我们正在尝试做的事情。

手动修改 PDF 文件不是一种选择,因为我们将它们直接通过电子邮件发送给我们的用户。

Jaspersoft 支持吗?

没有JasperReports版本<=6.7.0 支持这个,Configuration Reference中没有可用的属性来设置Lang 属性 到单个 textElement。

您有 2 个选择:

  1. Post 用 iText 作为 Dave Jarvis 详述 pdf。您可以尝试更改字典或重新创建 pdf 添加此附加信息。这些方法都相当复杂,自然会增加运行时间,因为您需要 read/recreate pdf。

  2. 修改 source code 的 JasperReport 以添加支持。直接修改 JRPdfExporter、JRPdfExporterTagHelper 或添加新的导出器(以保持原始库完好无损)

在这个答案中,我将向您展示如何修改原始库,添加额外的标签(在字典中添加 LANG 条目)

背景

example in PDF19: Specifying the language for a passage or phrase with the Lang entry in PDF documents,使用 iText RUPS 显示此 PDF 对象树。

我假设在我们的输出中添加 /Lang 就足够了,与不是 pdf 默认语言的特定文本相关。注意:如果您还需要添加其他条目,技术保持不变,您只需要修改下面的代码示例。

源码修改

Add a new property net.sf.jasperreports.export.pdf.tag.lang if this is present on reportElement in a type text field add a /Lang entry with its value to dictionary.

修改为JRPdfExporterTagHelper.java

添加静态属性标识符以遵循代码风格

public static final String PROPERTY_TAG_LANG = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.lang";

修改startText(boolean isHyperLink) and startText(String text, boolean isHyperlink),本例只显示第一个方法(第二个主体相同),我们需要更改方法签名添加JRPrintText这样我们就可以检索属性。

protected void startText(JRPrintText text, boolean isHyperlink)
    {
        if (isTagged)
        {

            PdfStructureElement textTag = new PdfStructureElement(tagStack.peek(), isHyperlink ? PdfName.LINK : PdfName.TEXT);
            if (text.hasProperties()&&text.getPropertiesMap().containsProperty(PROPERTY_TAG_LANG)){
                textTag.put(PdfName.LANG, new PdfString(text.getPropertiesMap().getProperty(PROPERTY_TAG_LANG)));
            }
            pdfContentByte.beginMarkedContentSequence(textTag);
        }
    }

由于我们更改了方法签名,我们现在需要修改 JRPdfExporter.java 以便我们可以重新编译

修改exportText(JRPrintText text)

...
if (glyphRendererAddActualText && textRenderer instanceof PdfGlyphRenderer)
{
    tagHelper.startText(text,styledText.getText(), text.getLinkType() != null);
}
else
{
    tagHelper.startText(text,text.getLinkType() != null);
}
...

您可以删除布尔值 text.getLinkType() != null,因为我们现在实际上正在传递文本对象,但为了示例的简单性,我想保留类似的代码

例子

jrxml

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TaggedPdf" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="1be2df3d-cbc1-467c-8729-1ed569eb8a0d">
    <property name="net.sf.jasperreports.export.pdf.tagged" value="true"/>
    <property name="net.sf.jasperreports.export.pdf.tag.language" value="EN-US"/>
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
    <queryString>
        <![CDATA[]]>
    </queryString>
    <title>
        <band height="67" splitType="Stretch">
            <staticText>
                <reportElement x="0" y="0" width="240" height="30" uuid="0722eadc-3fd6-4c4d-811c-64fbd18e0af5"/>
                <textElement verticalAlignment="Middle"/>
                <text><![CDATA[Hello world]]></text>
            </staticText>
            <staticText>
                <reportElement x="0" y="30" width="240" height="30" uuid="5080190e-e9fd-4df6-b0f6-f1be3c109805">
                    <property name="net.sf.jasperreports.export.pdf.tag.lang" value="FR"/>
                </reportElement>
                <textElement verticalAlignment="Middle"/>
                <text><![CDATA[Bonjour monde]]></text>
            </staticText>
        </band>
    </title>
</jasperReport>

导出为 pdf 并进行上述修改并使用 iText RUPS 可视化

根据 PDF19 是否足够:在 PDF 文档中使用 Lang 条目指定段落或短语的语言

Verify that the language of a passage, phrase, or word that differs from the language of the surrounding text is correctly specified by a /Lang entry on an enclosing tag or container:

据我所知,是的,但我不是这方面的专家,无论如何,如果您需要添加其他标签,过程是相同的。