问题
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