5

I'm creating a javascript interface to dynamically add xlinked images to a map of a classroom.

 //declare the xlink namespace in the svg header
 xmlns:xlink="http://www.w3.org/1999/xlink"
...
//the code to append the image
var temp = document.createElementNS(svgns,"image");
temp.setAttributeNS(null,"x","0");
temp.setAttributeNS(null,"y","0");
temp.setAttributeNS(null,"height","80");
temp.setAttributeNS(null,"width","40");
temp.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href","roomlayouts/items/ cactus.svg");

The image appends and displays on the screen with tags like so:

<image x="0" y="0" height="80" width="40" xlink:href="roomlayouts/items/cactus.svg"></image>

But once I pass it through the xmlserializer so that I can save the file, it strips the xlink tag off the front:

var svgDoc = document.getElementById('SVGMap');
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(svgDoc.firstChild);

creating:

<image x="0" y="0" width="40" height="80" href="roomlayouts/items/cactus.svg"></image>

This means the svg loses the cactii. Any ideas how I can get the xmlserializer to keep the xlink prefix?

============================== NOTE: this was a bug in webkit that has now been resolved. See discussion below for link to bug report

pluke
  • 3,832
  • 5
  • 45
  • 68

1 Answers1

4

Further Investigation

I have created a test SVG file on my server that:

  1. Has an <image> with properly-namespaced href attribute in it.
  2. Uses JS to create a new <image> using setAttributeNS(xlinkNS,'xlink:href',…)
  3. Uses JS to create a new <image> using setAttributeNS(xlinkNS,'href',…)
  4. Uses JS to clone the original (valid) <image> element.
  5. Finally, serializes the XML and logs the result.

Results in WebKit

The Safari and Chrome Developer Tools both show the DOM as:

<image xlink:href="…" />
<image xlink:href="…" />
<image href="…" />
<image xlink:href="…" />

However, the XML serialization logged to the console (which is what you also get if you right click the Element and say "Copy as HTML") shows this:

<image xlink:href="…" />
<image xlink:href="…" />
<image href="…" xmlns="http://www.w3.org/1999/xlink" />
<image xlink:href="…" />

Results in Firefox

Firebug also shows this for the generated DOM:

<image xlink:href="…" />
<image xlink:href="…" />
<image href="…" />
<image xlink:href="…" />

However, the Firebug Console shows a reasonable (expected) serialization:

<image xlink:href="…" />
<image xlink:href="…" />
<image xlink:href="…" />
<image xlink:href="…" />

Further investigation shows that even if you use code like:

img.setAttributeNS(xlinkNS,'GLARBLE:href',…);

Firebug will show "GLARBLE:href" as the name of the attribute, but the XML serialization uses the URI for the namespace, finds the matching namespace on the root <svg> element and properly produces:

<image xlink:href="…" />

Conclusion

It appears that the XML serialization performed by Webkit is flawed (broken) when using setAttributeNS to create a namespaced attribute with no namespace prefix provided for the attribute name.

However, if you provide a namespace prefix for the attribute name that matches a namespace prefix already declared on your document, the serialization appears to work correctly.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • Hi Phrogz, You're making me think that my issue might lie elsewhere. Once I make the svg, I serialise it and save it. When I try and reload it everything loads but the plants. If I edit the file and add the xlink: before the html tag then they appear, hence my attempt to use xlink:html instead of plain html. Any idea why they aren't appearing? – pluke Jan 23 '12 at 23:57
  • @pluke See my update and investigation. Are you creating your `` element programmatically, and if so how/where are you setting a general XLink namespace prefix? – Phrogz Jan 24 '12 at 04:30
  • I'm using: with some other name space declarations. Does that sound ok? I need to look more closely at your code and see if there are any differences. As far as I can see when I dynamically create the image it displays in the same way as your [2.] but when I serialise it to save it the xlink is stripped and when I reload it it won''t display at all. – pluke Jan 24 '12 at 09:34
  • If you use `var xlinkNS = svg.getAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink');` instead it works in Opera but not the others, if OTOH you do `var xlinkNS = svg.getAttributeNS('http://www.w3.org/2000/xmlns/', 'xlink');` then it works in all of them. NOTE: With "works" I only mean that the image shows up four times, not that it's serialized the same way. Also see http://www.w3.org/TR/DOM-Level-3-Core/core.html#Namespaces-Considerations. – Erik Dahlström Jan 24 '12 at 13:39
  • I think I've found part of the issue, when I programmatically make the svg, I build the svg header tag as a string with the code: `` but once this is serialised it strips off the xmlns: leaving: `` meaning it doesn't handle the xlink correctly. Any ideas on how to stop the serialiser doing all this tag stripping? – pluke Jan 24 '12 at 23:19
  • @pluke Why don't you build the `` node programmatically and set the `xmlns:xlink` attribute directly on there? – Phrogz Jan 25 '12 at 00:50
  • @Phrogz, I'll give it a shot and let you know if that fixes anything. – pluke Jan 25 '12 at 08:53
  • @Phrogz. I've constructed it programmatically: `var xmlns = "http://www.w3.org/2000/svg"; var newEl = document.createElementNS(xmlns,"svg"); newEl.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', xmlns); newEl.setAttributeNS(xmlns,"xlink","http://www.w3.org/1999/xlink"); newEl.setAttributeNS(xmlns,"dc","http://purl.org/dc/elements/1.1/"); ...` But it's not making much of a difference, and won't let me `setAttributeNS(xmlns,"xmlns:xlink","http://www.w3.org/1999/xlink");` complaining of a NAMESPACE_ERR DOM Ex 14 – pluke Jan 26 '12 at 22:15
  • `ewEl.setAttributeNS(xmlns,"xlink","http://www.w3.org/1999/xlink");` should be `ewEl.setAttributeNS('http://www.w3.org/2000/xmlns/',"xmlns:xlink","http://www.w3.org/1999/xlink");` – Phrogz Jan 27 '12 at 02:59
  • @Phrogz still having no luck, the chrome serializer butchers the xmlns tag out of the svg. Firebox does a better job, serializing the svg code so it displays in chrome, but bizarrely not in firefox. I haven't tested in IE. Take a look at the example here: http://kemputing.com/demo/importImage.html – pluke Jan 28 '12 at 20:18
  • FYI this is now registered as a bug and in the process of getting fixed: https://bugs.webkit.org/show_bug.cgi?id=79586 – pluke Apr 28 '12 at 08:39