Polish special letters not available while using Apache FOP

谁说我不能喝 提交于 2019-12-07 23:56:07

问题


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

回答1:


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


来源:https://stackoverflow.com/questions/51258443/polish-special-letters-not-available-while-using-apache-fop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!