使用Apache FOP时无法使用波兰语特殊字母

时间:2018-07-10 06:24:27

标签: java java-8 apache-fop polish

使用FOP(带有波兰字母)生成PDF时,我一直很努力。我在这里已经阅读了很多关于SO的文章,但到目前为止没有成功!

这是我的模板:

<?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>

还有我的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>

和我的Java代码调用它:

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();
    }
}

在我的模板中可以看到,我使用Arial作为字体系列,如果我在单词中键入文字,则使用Arial效果很好。但是从Java调用时

我收到很多警告:

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

所以我的问题是(原因)我在做什么错?

即使我已指定Arial,FOP为何会选择“ Times-Roman”?更重要的是如何解决它?

**更新**

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

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();
    }
}

1 个答案:

答案 0 :(得分:3)

This answer可能包含一些有用的信息。所有错误都是由于找不到Arial字体引起的,这就是为什么它切换到Times-Roman的原因,在那里找不到特殊字符(由于某种原因)。

因此,如该答案所示,为FOP添加配置xml,其中包含以下内容以引用系统中的Arial字体:

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>

使用File对象在FopFactory构造函数中添加对该配置文件的引用:

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

现在文件应该呈现并且字体应该正确:

C:\ Temp \ PolishTest.pdf

PDF screen-shot

编辑: 经过进一步测试后,我有了<auto-detect />标签的运气。但是,在尝试搜索字体时,渲染花费了更多时间。如果您不知道字体文件的位置,这可能会很有用。您可能需要尝试一下:

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