1

I am trying to add a PNG image to SVG. I have found that I need to add the following two snippet:

<clipPath id="circleView">
<circle cx="1500" cy="1500" r="125" fill="#FFFFFF" />
</clipPath>

<image xmlns:xlink="http://www.w3.org/1999/xlink" x="1250" y="1375" width="500" height="250" xlink:href="https://www.amrita.edu/sites/default/files/news-images/new/news-events/images/l-nov/grass.jpg" clip-path="url(#circleView)" />

Opening the main file with Element tree python library shifts everything to ns0 namespace, so the following code doesn't do what is intended:

tree = ET.parse(fname)
root = tree.getroot()
xmlns = '{http://www.w3.org/2000/svg}'
cp_string = '''<clipPath id="circleView">
            <circle cx="1500" cy="1500" r="125" fill="#FFFFFF" />            
        </clipPath>'''
img_string = '''<image xmlns:xlink="http://www.w3.org/1999/xlink" x="1250" y="1375" width="500" height="250" xlink:href="https://www.amrita.edu/sites/default/files/news-images/new/news-events/images/l-nov/grass.jpg" clip-path="url(#circleView)" />'''

tree.getroot().set("xmlns:xlink", "http://www.w3.org/1999/xlink")
defs = root.find(xmlns+'defs')   
cp = ET.fromstring(cp_string)
img = ET.fromstring(img_string)
defs.append(cp)
root.append(img)
tree.write('mod.svg')

The output skeletal SVG is below:

`<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" xmlns:ns1="http://www.w3.org/1999/xlink" height="3000px" version="1.1" width="3000px" xmlns:xlink="http://www.w3.org/1999/xlink">
<ns0:defs>
<ns0:pattern height="10" id="checker" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:5" x1="0" x2="10" y1="0" y2="0" /><ns0:line style="stroke:black;stroke-width:4" x1="0" x2="0" y1="0" y2="10" /></ns0:pattern>
<ns0:pattern height="10" id="checker" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:2" x1="0" x2="10" y1="0" y2="0" /><ns0:line style="stroke:black;stroke-width:2" x1="0" x2="0" y1="0" y2="10" /></ns0:pattern>
<ns0:pattern height="10" id="hline" patternTransform="rotate(0 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:5" x1="0" x2="10" y1="0" y2="0" /></ns0:pattern>
<ns0:pattern height="10" id="vline" patternTransform="rotate(0 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:5" x1="0" x2="0" y1="0" y2="10" /></ns0:pattern>
<ns0:pattern height="10" id="hline-sparse" patternTransform="rotate(0 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:2" x1="0" x2="10" y1="0" y2="0" /></ns0:pattern>
<ns0:pattern height="10" id="vline-sparse" patternTransform="rotate(0 0 0)" patternUnits="userSpaceOnUse" width="10"><ns0:line style="stroke:black;stroke-width:2" x1="0" x2="0" y1="0" y2="10" /></ns0:pattern>
<clipPath id="circleView">
            <circle cx="1500" cy="1500" fill="#FFFFFF" r="125" />            
        </clipPath></ns0:defs>
<image clip-path="url(#circleView)" height="250" width="500" x="1250" y="1375" ns1:href="https://www.amrita.edu/sites/default/files/news-images/new/news-events/images/l-nov/grass.jpg" /></ns0:svg>`

The SVG doesn't show the image because (as far as I can tell) is in the wrong namespace. I can edit that manually or hardcode it, but it all seems hacky and wrong. What would be the proper way of editing a SVG in Python?

Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
Cindy Almighty
  • 903
  • 8
  • 20
  • You say the code doesn't work but refer to the svg not showing the image. Does that mean the code runs and produces output ? If so, can you inspect the resulting svg, possibly adding it ( or say: a skeletal version only containing the relevant portions, ie. `svg` element, `#circleView` element and dependents, and the `image` element ) to the question ? – collapsar Feb 14 '18 at 11:28
  • Done! Thank you @collapsar – Cindy Almighty Feb 14 '18 at 11:49
  • The svg neither contains the clip path nor the image element. Try to prefix the literal element names in your python code with the local name `ns0` of the svg namespace, ie ``. You may also try to drop the `xmlns` variable and its uses from your python code. – collapsar Feb 14 '18 at 11:59
  • Again I managed to post the wrong SVG. The image shows when I manually add ns0 tags. Is there a better way, a smarter parser? Is there a way to extract the namespaces? (ET doesn't seem to show it) – Cindy Almighty Feb 14 '18 at 12:09
  • I'm not fluent in python but maybe [this SO answer](https://stackoverflow.com/a/14853417) can help you. When it comes to `lxml`, I've had a favorable experience with the underlying libxml library and its Perl wrapper in a fairly complex project involving a mix of various namespaces (default and named), so I tend to recommend switching to that lib (it claims to have the same `ElementTree` interface so your source code should run with minor modifications). – collapsar Feb 14 '18 at 13:03

0 Answers0