使用 Apache FOP 时波兰语特殊字母不可用 [英] Polish special letters not available while using Apache FOP

查看:27
本文介绍了使用 Apache FOP 时波兰语特殊字母不可用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力使用 FOP 生成带有波兰语字母的 PDF.我已经在这里阅读了很多关于 SO 的帖子,但到目前为止都没有成功!

这是我的模板:

<xsl:template match="root"><fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"><fo:layout-master-set><fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm"><fo:region-body/></fo:simple-page-master></fo:layout-master-set><fo:page-sequence master-reference="simpleA4"><fo:flow flow-name="xsl-region-body"><fo:block font-size="11pt" font-family='Arial'><xsl:value-of select="TestString"/></fo:block></fo:flow></fo:page-sequence></fo:root></xsl:模板></xsl:stylesheet>

还有我的 XML:

<TestString>Chcemy mieć pewność, że nasze produkty będą miały długą żywotność i stosujemy opakowania, aby uchronić je przed uszkodzeniem podczas&prizen.</root>

和我调用它的 Java 代码:

private void PolishTest() 抛出 IOException、FOPException、TransformerException {//XSL FO 文件File xsltFile = new File("C:\\Temp\\PolishTest.xsl");//提供输入的 XML 文件StreamSource xmlSource = new StreamSource(new File("C:\\Temp\\PolishTest.xml"));//创建一个 fop 工厂的实例FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());//转换需要用户代理FOUserAgent foUserAgent = fopFactory.newFOUserAgent();//设置输出OutputStream out = new FileOutputStream("C:\\Temp\\PolishTest.pdf");尝试 {//用所需的输出格式构造 fopFop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);//设置 XSLTTransformerFactory 工厂 = TransformerFactory.newInstance();Transformer 变压器 = factory.newTransformer(new StreamSource(xsltFile));//产生的 SAX 事件(生成的 FO)必须通过管道传送到 FOP结果 res = new SAXResult(fop.getDefaultHandler());//启动 XSLT 转换和 FOP 处理//这是 XML 首先转换为 XSL-FO 的地方,然后//PDF被创建转换器.transform(xmlSource, res);} 最后 {关闭();}}

正如在我的模板中看到的,我使用 Arial 作为字体系列,如果我在 word 中输入文本,使用 Arial 效果非常好.但是当从 Java 调用它时

我收到很多警告:

七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:找不到字体Arial,normal,400".替换为any,normal,400".七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ć"(0x107,cacute)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ś"(0x15b,sacute)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ż"(0x17c,zdot)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ę"(0x119,eogonek)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ą"(0x105,aogonek)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent警告:字形ł"(0x142,lslash)在字体Times-Roman"中不可用.七月.2018 年 10 月 10 日上午 8:16:57 org.apache.fop.events.LoggingEventListener processEvent

所以我的问题是(因为)我做错了什么?

即使我指定了 Arial,FOP 怎么会选择Times-Roman"?更重要的是如何修复它?

** 更新 **

使用 am9417 的答案中的代码,我将 Java 代码更新为以下内容:

private static String config = "\n" +" <渲染器>\n" +" <renderer mime=\"application/pdf\">\n" +" <字体>\n" +" <自动检测/>\n" +" </fonts>\n" +" </renderer>\n" +" </renderers>\n" +"</fop>";private void PolishTest() 抛出 IOException、SAXException、TransformerException {//XSL FO 文件File xsltFile = new File("C:\\Temp\\PolishTest.xsl");//提供输入的 XML 文件StreamSource xmlSource = new StreamSource(new File("C:\\Temp\\PolishTest.xml"));//创建一个 fop 工厂的实例URI uri = new File(".").toURI();InputStream configSource = new ByteArrayInputStream(config.getBytes());FopFactory fopFactory = FopFactory.newInstance(uri, configSource);//转换需要用户代理FOUserAgent foUserAgent = fopFactory.newFOUserAgent();//设置输出OutputStream out = new FileOutputStream("C:\\Temp\\PolishTest.pdf");尝试 {//用所需的输出格式构造 fopFop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);//设置 XSLTTransformerFactory 工厂 = TransformerFactory.newInstance();Transformer 变压器 = factory.newTransformer(new StreamSource(xsltFile));//产生的 SAX 事件(生成的 FO)必须通过管道传送到 FOP结果 res = new SAXResult(fop.getDefaultHandler());//启动 XSLT 转换和 FOP 处理//这是 XML 首先转换为 XSL-FO 的地方,然后//PDF被创建转换器.transform(xmlSource, res);} 最后 {关闭();}}

解决方案

在进一步测试之后,我对 <auto-detect/> 标签很幸运.但是,渲染在尝试搜索字体时花费了更多时间.如果您不知道字体文件位置,这可能很有用.您可能想尝试一下:

<预><代码>...<字体><自动检测/></字体>...

I've been struggling a lot with generating a PDF using FOP, with Polish letters. I have been reading a lot of posts here on SO but so far no success!

Here is my Template:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:template match="root">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="simpleA4">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-size="11pt" font-family='Arial'>
            <xsl:value-of select="TestString"/>
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>
</xsl:stylesheet>

And my XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <TestString>Chcemy mieć pewność, że nasze produkty będą miały długą żywotność i stosujemy opakowania, aby uchronić je przed uszkodzeniem podczas przenoszenia i transportu.</TestString>
</root>

and my Java code calling it:

private void PolishTest() throws IOException, FOPException, TransformerException {
    // the XSL FO file
    File xsltFile = new File("C:\\Temp\\PolishTest.xsl");
    // the XML file which provides the input
    StreamSource xmlSource = new StreamSource(new File("C:\\Temp\\PolishTest.xml"));
    // create an instance of fop factory
    FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
    // a user agent is needed for transformation
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

    // Setup output
    OutputStream out = new FileOutputStream("C:\\Temp\\PolishTest.pdf");

    try {
        // Construct fop with desired output format
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        // Setup XSLT
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));

        // Resulting SAX events (the generated FO) must be piped through to FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        // Start XSLT transformation and FOP processing
        // That's where the XML is first transformed to XSL-FO and then
        // PDF is created
        transformer.transform(xmlSource, res);
    } finally {
        out.close();
    }
}

as seen in my template I'm using Arial as font family, and if I type the text in word, using Arial it works out very fine. But when calling it from Java

I get a lot of warnings:

jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Font "Arial,normal,400" not found. Substituting with "any,normal,400".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ć" (0x107, cacute) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ś" (0x15b, sacute) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ż" (0x17c, zdot) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ę" (0x119, eogonek) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ą" (0x105, aogonek) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "ł" (0x142, lslash) not available in font "Times-Roman".
jul. 10, 2018 8:16:57 AM org.apache.fop.events.LoggingEventListener processEvent

So my question is (ofcause) what am I doing wrong?

How come FOP chooses "Times-Roman", even though I've specified Arial? And more important how to fix it?

** UPDATE **

With the code from am9417's answer I've updated my Java code to the following:

private static String config = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
        "<fop>\n" +
        "  <renderers>\n" +
        "    <renderer mime=\"application/pdf\">\n" +
        "      <fonts>\n" +
        "        <auto-detect/>\n" +
        "      </fonts>\n" +
        "    </renderer>\n" +
        "  </renderers>\n" +
        "</fop>";

private void PolishTest() throws IOException, SAXException, TransformerException {
    // the XSL FO file
    File xsltFile = new File("C:\\Temp\\PolishTest.xsl");
    // the XML file which provides the input
    StreamSource xmlSource = new StreamSource(new File("C:\\Temp\\PolishTest.xml"));
    // create an instance of fop factory

    URI uri =  new File(".").toURI();
    InputStream configSource = new ByteArrayInputStream(config.getBytes());

    FopFactory fopFactory = FopFactory.newInstance(uri, configSource);
    // a user agent is needed for transformation
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();


    // Setup output
    OutputStream out = new FileOutputStream("C:\\Temp\\PolishTest.pdf");

    try {
        // Construct fop with desired output format
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        // Setup XSLT
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));

        // Resulting SAX events (the generated FO) must be piped through to FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        // Start XSLT transformation and FOP processing
        // That's where the XML is first transformed to XSL-FO and then
        // PDF is created
        transformer.transform(xmlSource, res);
    } finally {
        out.close();
    }
}

解决方案

This answer might contain some useful information. All the errors are caused because Arial font is not found, that's why it switches to Times-Roman where special characters (for some reason) cannot be found.

So, as in that answer, add the config xml for the FOP with the following content to refer to the Arial font in your system:

C:\Temp\fopconf.xml

<?xml version="1.0" encoding="utf-8" ?>
 <fop>
   <renderers>
    <renderer mime="application/pdf">
     <fonts>                           
        <font kerning="yes" embed-url="file:///C:/windows/fonts/arial.ttf">
            <font-triplet name="Arial" style="normal" weight="normal"/>
        </font>                     
    </fonts>
    </renderer>
  </renderers>
 </fop>

Add the reference to that config file in the FopFactory constructor with a File object:

// create an instance of fop factory
FopFactory fopFactory = FopFactory.newInstance(new File("C:\\Temp\\fopconf.xml"));

Now the file should render and the font should be correct:

C:\Temp\PolishTest.pdf

EDIT: After testing this further, I had luck with <auto-detect /> tag. However, rendering took a bit more time when it tried to search the fonts. This might be useful if you don't know the font file location. You might want to give it a try:

...
<fonts>                           
    <auto-detect/>                    
</fonts>
...

这篇关于使用 Apache FOP 时波兰语特殊字母不可用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆