0

I have some SVG files that I'd like to create a PDF with. For simplicity lets assume each one represents one page in the PDF. There is a node in the SVG containing some text that I would like to exclude. How do I go about doing so? Here's a sample SVG file and fo to include it as a page in the PDF.

Lets say there exists a file named /home/dave/images/some_image.svg containing this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="470" height="363" xml:space="preserve">
  <g clip-path="url(#some-path)">
    <rect id="some-rect" fill="#FFFFFF" stroke="#666" height="363" width="470" opacity="1" x="0" y="0"/>
    <defs id="some-defs">
      <clipPath id="some-path" x="0" y="0" width="100%" height="100%">
        <rect height="363" x="0" y="0" width="470" fill="#fff"/>
      </clipPath>
    </defs>
    <g id="some-group">
      <path id="a-path"/>
      <g id="a-container">
        <text id="some-text" x="235" y="181">This text needs to go</text>
        <image x="-2000" y="-1500" width="4000" height="3000" xlink:href="http://www.somewebsite.com/image.jpg" id="some-img"/>
      </g>
    </g>
  </g>
</svg>

and now for a sample fo that uses it

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

  <fo:layout-master-set>
    <fo:simple-page-master master-name="page" margin="0pt"
                           page-height="363pt" page-width="470pt">
      <fo:region-body />
    </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence master-reference="page">
    <fo:flow flow-name="xsl-region-body">
      <fo:block>
        <fo:external-graphic 
            src='/home/dave/images/some_image.svg'/>
      </fo:block>
    </fo:flow>
  </fo:page-sequence>

</fo:root>

So this works fine for including the whole svg "as is". How can I exclude the text node?

<text id="some-text" x="235" y="181">This text needs to go</text>

As for the real files I'm using they reference a font that I won't need to include in the PDF and the text will be behind the image anyway thus not viewable.

Khorkrak
  • 3,911
  • 2
  • 27
  • 37
  • How are you creating the XSL-FO? – Daniel Haley Jul 15 '11 at 23:06
  • Just manually for now. I'll have to generate either the xsl-fo or xslt programmatically later on somehow - probably with python and lxml. So while doing that I could process the svg files and strip out the unwanted node(s) but I'm wondering if there's a more elegant, declarative solution using xsl. – Khorkrak Jul 15 '11 at 23:47
  • 3
    I'm no FO guru but I would go for stripping the undesired node in an XSLT step. Svg is after all a form of xml. – Wivani Jul 18 '11 at 09:38

1 Answers1

1

Keeping <fo:external-graphic /> : XSLT pre-processing

If you want or need to keep the <fo:external-graphic /> approach, then you should certainly pre-process your SVG using XSLT, as suggested by Wivani

A copy-all template and a remove template should be enough, like:

<xsl:template match="node()|@*">
  <xsl:copy>
     <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="text[@id='some-text']"/>

You can keep your FO as-is, maybe changing the SVG path to the new, pre-processed SVG:

<fo:external-graphic src='/home/dave/images/some_image_stripped.svg'/>

For more specific info, see other SO questions like:

Alternative using <fo:instream-foreign-object />

If, on the other hand, you want to keep a one-step process, you can investigate at inlining you SVG in your XML-FO, using <fo:instream-foreign-object />.

But this would likely require you to change your processing logic, creating the XML-FO by means of an XSL transformation from your SVG file. This could conflict with other requirements of yours.

You can have a look at Displaying SVG using XSLFO for more info on this technique.

Community
  • 1
  • 1
Alain BECKER
  • 787
  • 5
  • 15