I am generating a PDF using Apache FOP 2.1, JAXB, and XSLT 1.0. The template has some embedded SVGs. The PDF renders without any issues, but FO is throwing errors that are cluttering up my logs.
Setup:
XslProcessor.java
public XslProcessor(File f) {
try {
URIResolverAdapter uriResolverAdapter = new URIResolverAdapter(new UserAgentUriResolver());
FopFactoryBuilder builder = new FopFactoryBuilder(URI.create("/"), uriResolverAdapter);
DefaultConfigurationBuilder defaultConfigurationBuilder = new DefaultConfigurationBuilder();
builder.setConfiguration(defaultConfigurationBuilder.buildFromFile("config/pdf/fop.xconf"));
fopFactory = builder.build();
transformerFactory = TransformerFactory.newInstance();
transformFile = f;
} catch (IOException | SAXException | ConfigurationException e) {
throw new RuntimeException(e);
}
}
public synchronized void process(InputStream is, OutputStream os) {
try {
try(BufferedOutputStream bufferedOut = new BufferedOutputStream(os)) {
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, bufferedOut);
Source xslt = new StreamSource(transformFile);
Transformer transformer = transformerFactory.newTransformer(xslt);
Source source = new StreamSource(is);
Result result = new SAXResult(fop.getDefaultHandler());
transformer.transform(source, result);
}
os.flush();
os.close();
} catch (IOException | FOPException | TransformerException e) {
throw new RuntimeException(e);
}
}
UserAgentUriResolver.java
public class UserAgentUriResolver implements URIResolver {
private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36";
private static final String REFERRER = "https://www.google.com";
@Override
public Source resolve(String href, String base) throws TransformerException {
try {
URL url = new URL(href);
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", USER_AGENT);
connection.setRequestProperty("Referrer", REFERRER);
return new StreamSource(connection.getInputStream());
} catch (IOException e) {
return new StreamSource(new ByteArrayInputStream(new byte[0]));
}
}
}
Sample template:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="29.7cm"
page-width="21cm">
<fo:region-body/>
<fo:region-after extent="1.25cm"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="all">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference master-reference="page"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="all">
<fo:static-content flow-name="xsl-region-after">
<fo:block>
<fo:instream-foreign-object>
<!-- SVG here! -->
<svg xmlns="http://www.w3.org/2000/svg" xml:base="http://www.example.com/">
<rect height="20" width="100%" fill="#ababab"></rect>
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Once for every svg in the template, I get
org.apache.fop.fo.FONode: Could not set base URL for svg
java.lang.IllegalArgumentException: URI is not absolute at java.net.URI.toURL(URI.java:1088) ~[na:1.8.0_91] at org.apache.fop.fo.extensions.svg.SVGElement.getDimension(SVGElement.java:77) ~[fop-2.1.jar:na] at org.apache.fop.fo.flow.InstreamForeignObject.prepareIntrinsicSize(InstreamForeignObject.java:112) [fop-2.1.jar:na] at org.apache.fop.fo.flow.InstreamForeignObject.getIntrinsicWidth(InstreamForeignObject.java:125) [fop-2.1.jar:na] at org.apache.fop.layoutmgr.inline.AbstractGraphicsLayoutManager.getInlineArea(AbstractGraphicsLayoutManager.java:60) [fop-2.1.jar:na] at ...
fo:instream-foreign-object
processed by FOP 2.1 causes a validation error (org.apache.fop.fo.ValidationException: "fo:instream-foreign-object" is missing child elements. Required content model: one (1) non-XSL namespace child), so there should be something else wrong in the OP's created svg trees. - lfurinifo:instream-foreign-object
is not empty. - nmatte