0

I'm trying to transform an svg with tcpdf to pdf. I'm using

$pdf->ImageSVG(
    $file=$my_source,...

Everyting works fine until there is an other svg image inserted inline in the $my_source like:

<image xlink:href='subSvg.svg'/>

but i always get error messages by tcpdf. Has anyone experiences with svg inserting sub-svg images in tcpdf?

Update:

I tried it again: it is only a warning. PDF is generated. Tcdpf has only trouble to free ressources of the sub svg: Warning: xml_parser_free(): 19 is not a valid XML Parser resource in tcpdf.php on line 22913

This is an example subSvg.svg

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="300" height="300" 
viewBox="0 0 300 300"
preserveAspectRatio="xMinYMin meet">
<desc>123456</desc>
<g id="elements" fill="black" stroke="none">
<rect x="0" y="0" width="30" height="30" />
</g>
</svg> 

Is it possible to reference the svg inline (data:image/svg+xml;utf8,)?

<image xlink:href='@<svg ...'/>
Thomas W
  • 14,757
  • 6
  • 48
  • 67
Hauke
  • 257
  • 4
  • 12

1 Answers1

0

You might consider pre-processing the SVG images, inlining the referenced SVG. Here's a draft of a possible approach using XSLT 2.0:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="2.0">

  <xsl:template match="node()|@*">
    <xsl:param name="attributes"/>

    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:copy-of select="$attributes"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>


  <xsl:template match="svg:image[matches(@xlink:href, '\.svg$')]">
    <xsl:variable name="imageUrl">
      <xsl:choose>
        <xsl:when test="contains(@xlink:href, '//')">
          <xsl:value-of select="@xlink:href"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="concat(replace(base-uri(), '/[^/]+$', '/'), @xlink:href)"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="imageDocument" select="document($imageUrl)"/>

    <xsl:if test="not($imageDocument)">
      <xsl:message terminate="yes">
        <xsl:value-of select="concat('Could not find image ', $imageUrl)"/>
      </xsl:message>
    </xsl:if>

    <xsl:apply-templates select="$imageDocument">
      <xsl:with-param name="attributes" select="(@x, @y, @width, @height, @transform)"/>
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

Make sure that

  • you're using an XSLT 2.0 processor (for XSLT 2.0 in a PHP context, see this post),
  • the referenced SVGs are accessible by the XSLT processor under the URLs in the xlink:href attributes,
  • SVGs do not reference each other recursively,
  • the outer SVG does not use CSS and style attributes that will result in undesired re-styling of the inner SVG,
  • the inlining does not cause ID collisions that could e.g. break <use> elements or filters.

Depending on how your SVG files look like, the XSLT might require refining, e.g. to rewrite IDs and ID references to address the last point.

Community
  • 1
  • 1
Thomas W
  • 14,757
  • 6
  • 48
  • 67
  • Interesting idea! I think, i have no need for automatic transformations. I could insert the data of the sub,svg directly into the file. But it would be much comfortable for me to use it as an image. – Hauke Jun 06 '16 at 10:12