I am making a script that auto-generates PDF documents from a template. The document is generated as an SVG, which should then be converted to a PDF using cairosvg. This step, however, fails when an embedded image is encountered.
<!-- test.svg -->
<svg viewBox="0 0 1 1" width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="0" y="0" width="1" height="1" fill="green"/>
<image x="0" y="0" width="1" height="1" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAATSURBVBhXYwCC/yACicZgMPwHAFnNBPyimoN0AAAAAElFTkSuQmCC"/>
</svg>
Cairosvg appears to be silently disregarding <image>
tags when converting to other formats, not just pdf.
import cairosvg
cairosvg.svg2pdf(url='test.svg', write_to='out.pdf')
cairosvg.svg2png(url='test.svg', write_to='out.png')
cairosvg.svg2svg(url='test.svg', write_to='out.svg')
In this example, all outputs are missing the embedded image. Even svg output, which yields
<!-- out.svg -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="75pt" height="75pt" viewBox="0 0 75 75" version="1.1">
<g id="surface7">
<rect x="0" y="0" width="75" height="75" style="fill:rgb(0%,50.196078%,0%);fill-opacity:1;stroke:none;"/>
</g>
</svg>
I have tried both filesystem paths and data URLs for href
, and running cairosvg from a command line. In all cases, the embeds were silently discarded.
I have seen examples of cairosvg converting documents with embedded images properly, but without any code I could compare mine against. How can the images be included in conversion?
<image>
tags are considered unsafe and they are not resolved unless unsafe mode is enabled explicitly.
From the documentation (cairosvg --help
):
-u, --unsafe resolve XML entities and allow very large files
(WARNING: vulnerable to XXE attacks and various DoS)
In the Python API, set the unsafe
parameter to true.
cairosvg.svg2pdf(url='test.svg', write_to='out.pdf', unsafe=True)