Forum How do I...?

Including images within SVGs in PHP

jkg9000
I've been successful at including an <image> tag within SVGs using the Windows desktop version of Prince. However, when I try to print the SVGs through the PHP version of Prince, I get everything in the SVG *except* the image.

Anybody know what might be causing this to happen, and how to resolve it?

Here's a very simple example, just an embedded image in a plain SVG:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100" height="298" transform="translate(0,0)">
<image xlink:href="http://gisdev.foundationcenter.org:7072/images/chart-marker-median.png" x="23" y="254.9" width="38" height="30" transform="translate(-19,-15)" stroke="#FFFFFF" stroke-width="0" fill="#89A54E" r="0" />
</g>
</svg>

This image will show up in the PDF when using the desktop app (when the code above is saved as XML), but won't show up at all in the PDF when going through PHP. Btw, I've tested the PHP version in both Windows and Linux, same result. PHP version 5.3.8.

Thx!
jake
mikeday
Which PHP convert method are you calling to generate the PDF file? If you call prince->setLog(...path...) do you get any error or warning messages in the log file?

Also, why is it defining the xlink namespace twice?
jkg9000
Hi Mike:

We're using convert_string_to_passthru.

Here's the error message we're getting, for every image it's trying to generate:
-- Wed Feb 20 13:41:56 2013: -: warning: svg: image: @xlink:href required.

However, each image does have an xlink:href attribute, like so:

<image preserveAspectRatio='none' xlink:href='http://swh-benchmarking.foundationcenter.org/images/chart-marker-median.png' x='26.000000000000004' y='265.2' width='38' height='30' transform='translate(-19,-15)' stroke='#FFFFFF' stroke-width='0.000001' fill='#89A54E' r='0'></image>

Is there anything in here that looks odd, that might be throwing it off? We tried replacing single quotes (') with double quotes ("), it didn't make a difference.

Would it be useful to see the entire SVG?
jake
mikeday
Yes, it would be useful to see the entire file. Since the attribute is there, the most likely possibility is that the xlink namespace has been defined with the wrong URL.
jkg9000
Here is the entire SVG:

<svg height='298' width='105' version='1.1' xmlns='http://www.w3.org/2000/svg'><g transform='translate(0,0)' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns='http://www.w3.org/2000/svg' version='1.1' width='105' height='298'><defs><clipPath id='highcharts-55'><rect fill='none' x='0' y='0' width='52' height='268'></rect></clipPath></defs><rect rx='5' ry='5' fill='#FFFFFF' x='0' y='0' width='105' height='298' stroke-width='0.000001'></rect><g class='highcharts-grid' ></g><g class='highcharts-grid' ></g><g class='highcharts-axis' ></g><g class='highcharts-axis' ></g><g class='highcharts-series-group' ><g class='highcharts-series' visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><rect fill='#8dd1ed' x='6.5' y='44.5' width='39' height='223' stroke-width='1' stroke='#FFFFFF' rx='0' ry='0'></rect></g><g class='highcharts-markers' visibility='visible' transform='translate(33,10)' clip-path='none'></g><g class='highcharts-series' visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><rect fill='#ffffff' x='6.5' y='267.5' width='39' height='0' stroke-width='1' stroke='#FFFFFF' rx='0' ry='0'></rect></g><g class='highcharts-markers' visibility='visible' transform='translate(33,10)' clip-path='none'></g><g class='highcharts-series' visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><path fill='none' d='M 0 0' stroke='black' stroke-width='5' stroke-opacity='0.049999999999999996' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='black' stroke-width='3' stroke-opacity='0.09999999999999999' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='black' stroke-width='1' stroke-opacity='0.15' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='#89A54E' stroke-width='2' ></path></g><g class='highcharts-markers' visibility='visible' transform='translate(33,10)' clip-path='none'><image preserveAspectRatio='none' xlink:href='http://swh-benchmarking.foundationcenter.org/images/chart-marker-median.png' x='26.000000000000004' y='265.2' width='38' height='30' transform='translate(-19,-15)' stroke='#FFFFFF' stroke-width='0.000001' fill='#89A54E' r='0'></image></g><g class='highcharts-series' visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><path fill='none' d='M 0 0' stroke='black' stroke-width='5' stroke-opacity='0.049999999999999996' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='black' stroke-width='3' stroke-opacity='0.09999999999999999' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='black' stroke-width='1' stroke-opacity='0.15' transform='translate(1, 1)'></path><path fill='none' d='M 0 0' stroke='#80699B' stroke-width='2' ></path></g><g class='highcharts-markers' visibility='visible' transform='translate(33,10)' clip-path='none'><image preserveAspectRatio='none' xlink:href='http://swh-benchmarking.foundationcenter.org/images/arrow-clipped-with-padding.png' x='26.000000000000004' y='267.9' width='38' height='29' transform='translate(-19,-14)' stroke='#FFFFFF' stroke-width='0.000001' fill='#80699B' r='0'></image></g></g><text x='60' y='293' style='font-family: verdana, arial, helvetica, sans-serif;font-size:9px;color:#666666;font-weight:normal;fill:#666666;' text-anchor='middle' class='highcharts-title' ><tspan x='60'>Accounting Fees</tspan></text><g class='highcharts-data-labels' visibility='visible' transform='translate(33,10)'></g><g class='highcharts-data-labels' visibility='visible' transform='translate(33,10)'></g><g class='highcharts-axis-labels' ></g><g class='highcharts-axis-labels' ><text x='25' y='284.1' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='25'>0</tspan></text><text x='25' y='235.0627189313327' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='25'>50</tspan></text><text x='25' y='186.02543786266543' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='25'>100</tspan></text><text x='25' y='136.98815679399814' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='25'>150</tspan></text><text x='25' y='87.95087572533086' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='25'>200</tspan></text><text x='0' y='0' style='font-family: verdana, arial, helvetica, sans-serif;font-size:8px;width:6px;color:#999999;line-height:14px;fill:#999999;' text-anchor='end'><tspan x='0'>250</tspan></text></g><g class='highcharts-tooltip' style='padding:0;white-space:nowrap;' visibility='hidden'><rect rx='0' ry='0' fill='none' x='0.5' y='0.5' width='10' height='10' stroke-width='5' fill-opacity='0.85' stroke='black' stroke-opacity='0.049999999999999996' transform='translate(1, 1)'></rect><rect rx='0' ry='0' fill='none' x='0.5' y='0.5' width='10' height='10' stroke-width='3' fill-opacity='0.85' stroke='black' stroke-opacity='0.09999999999999999' transform='translate(1, 1)'></rect><rect rx='0' ry='0' fill='none' x='0.5' y='0.5' width='10' height='10' stroke-width='1' fill-opacity='0.85' stroke='black' stroke-opacity='0.15' transform='translate(1, 1)'></rect><rect rx='0' ry='0' fill='rgb(255,255,255)' x='0.5' y='0.5' width='10' height='10' stroke-width='1' fill-opacity='0.85'></rect><text x='5' y='17' style='font-family: verdana, arial, helvetica, sans-serif;font-size:11px;color:#333333;fill:#333333;' ></text></g><g class='highcharts-tracker' ><g visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><rect fill='rgb(192,192,192)' x='6.5' y='44.5' width='39' height='223' fill-opacity='0.0001' visibility='visible' style=''></rect></g><g visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><rect fill='rgb(192,192,192)' x='6.5' y='265' width='39' height='6' fill-opacity='0.0001' visibility='visible' style=''></rect></g><g visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><path fill='none' d='M 16.000000000000004 265.2 L 36 265.2' stroke-linejoin='round' visibility='visible' stroke-opacity='0.0001' stroke='rgb(192,192,192)' stroke-width='22' style=''></path></g><g visibility='visible' transform='translate(33,10)' clip-path='url(#highcharts-55)'><path fill='none' d='M 16.000000000000004 267.9 L 36 267.9' stroke-linejoin='round' visibility='visible' stroke-opacity='0.0001' stroke='rgb(192,192,192)' stroke-width='22' style=''></path></g></g></g></svg>
mikeday
So when you call convert_string_to_passthru, is this the exact string that you are passing to it?
jkg9000
I'm actually sending it a bunch more stuff, but it's these images within the SVGs that aren't appearing. Everything else (tables, divs, CSS, SVGs without images) is fine.

I can send you the entire string.
jkg9000
Hi Mike --

The full string we're sending has 165k characters, beyond the max characters allowed in the forum.

Here it is, on WeTransfer.com:
https://www.wetransfer.com/downloads/b5ecb485ae11a9000f36048ce3bec78d20130222154439/6b9ad316c1e58c8c104df2c9955829c420130222154439/13badd
mikeday
Thanks. The issue here is that our HTML parser is mangling the XML namespace attributes in the embedded SVG. Hopefully we can fix this in our upcoming HTML5 parser. In the meantime, your document is already well-formed XML, so you could use the XML parser instead, with "-i xml" on the command-line, or setHTML(false) in PHP. Does this help?
jkg9000
We just tried it, it still doesn't work. Can we consult you by phone? Is there a planned schedule for fixing this, or is there another workaround?

I think we're at risk for not including PDF functionality for project launch -- anything you can think of would be much appreciated!
jake
mikeday
Using the XML parser also works on the sample document that you posted, how did it not work when you tried it? Was it still the xlink:href issue, or a new error?

We can provide you with an updated build of Prince with a HTML5 parser that fixes the problem of the SVG xlink:href attributes. Just email me (mikeday@yeslogic.com) and let me know which operating system you are running Prince on.