11

I am trying to use the JavaScript DOM API's XMLSerializer to convert an SVG element to its representative markup.

This is the basic code used to create the element and serialize it:

var el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
el.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
el.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');

var markup = (new XMLSerializer()).serializeToString(el);
console.log(markup);

In Chrome, Firefox, Safari and Opera, it produces what I want:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>

But in Internet Explorer 9 through to IE11, I get this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xml:NS1="" NS1:xmlns:xlink="http://www.w3.org/1999/xlink" />

There are two problems with IE's output:

  1. There are duplicate xmlns attributes. If I omit the second line of the JavaScript, then in IE there is just only one xmlns attribute in the markup, but in Firefox, Chrome, Safari and Opera, the attribute is missing.
  2. It adds xml:NS1="". Why is this? NS1: is then prefixed to the xmlns:xlink attribute.

I think that I'm creating the attributes the correct way. For example, using setAttribute instead of setAttributeNS is correct here (more info), and changing this doesn't seem to fix the problem.

Any insights appreciated.

Edit: a related issue discusses a bug in Chrome's serialization that leads to the omission of namespaces. Partially relevant to the first problem (although all the other browsers act the same), but not relevant to the second problem.

Community
  • 1
  • 1
Prem
  • 15,911
  • 11
  • 31
  • 35
  • The setAttribute calls seem wrong altogether. Doesn't it work better if you omit them completely? – Robert Longson Oct 26 '13 at 20:50
  • Unfortunately, I can't omit them. If I do, the result is just ``. I want the output markup to be something that can be saved as a .svg file and then that file opened as a standalone SVG image. The image won't work if the `xmlns` and `xmlns:xlink` are missing (the xlink attribute is needed to satisfy links in other elements withing the SVG. – Prem Oct 27 '13 at 07:56
  • The output from which browser? Are you doing this in a html document rather than an SVG or XHTML one? Firefox certainly does put the namespaces on when XMLSerialiser is run on an XML document? – Robert Longson Oct 27 '13 at 11:08
  • In an HTML page / in the browser's console. I was using Chrome but also testing in other browsers. Yes, namespaces are output in all the browsers, except an older version of WebKit (still in Safari 6.05 and PhantomJS) that has a bug where it omits the namespaces. The problem I had is now solved (see my answer below) - I needed to change the way I was setting the attributes. – Prem Oct 28 '13 at 14:16

1 Answers1

15

OK, I think I've solved it. Followed the trail from this post to this WebKit bug report and this test case.

If I change the script to this, then it works:

var el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
el.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg');
el.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink');

var markup = (new XMLSerializer()).serializeToString(el);
console.log(markup);

Ah namespaces.

But, it fails in an older version of WebKit that is still present in Safari 6.05 and PhantomJS (bug report - now fixed). Presumably the fix is incorporated into the latest Safari update (I haven't yet checked).

Community
  • 1
  • 1
Prem
  • 15,911
  • 11
  • 31
  • 35