IE adds double XMLNS on SVG markup when converting to string
Tags: ie, xmlserializer, svg, fix
Published: 2021-05-10 02:29:47

We where tasked/needed to serialize SVG files on a project we are working on, and while the first implementation worked well on most (normal) browsers, it did not take too long time before we got some complains that our images where not being displayed properly.

After some debugging we found out that all these cases where related to users using IE. And after dusting of my Windows laptop and started testing we could reproduce the issue ❤️ (as developer I get a relief when I can reproduce an bug)

After a quick search on Google for `IE svg adding double xmlns` following two links helped understanding the issue and led to a fix:

- [Unwanted namespaces on SVG markup when using XMLSerializer in JavaScript with IE](https://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie)
- [Highcharts adds duplicate xmlns attribute to SVG element in IE](https://stackoverflow.com/questions/17265376/highcharts-adds-duplicate-xmlns-attribute-to-svg-element-in-ie) 

## First implementation (Does NOT work on IE)

We do use Figma to design and create our SVG's, when exporting, the SVG contains the `xmlns`-tag by default.

Here is an SVG example showing a red circle where the `xmlns`-tag is already set:
```html
<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red" />
</svg> 
```

The serialize function we used is straight forward using `XMLSerializer`:
```ts
export const svgSerialize = (el: SVGSVGElement) => new XMLSerializer().serializeToString(el);
```

This will result in following result:
```html
<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red"/></svg>
```

And as said this worked perfectly on all other browsers expect Internet Explorer. Here is the result of same image on IE:

```html
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red"/></svg>
```

Yes you spotted right, yet another `xmlns="http://www.w3.org/2000/svg"`-tag has been added to the SVG :(

Browsers are strict on XML parsing and therefor the above image will not be displayed!

After some trial and errors here is how we fixed the issue.

## The solution

First we removed `xmlns` tag from our SVG:
```html
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red" />
</svg> 
```

And our new svgImageToString function looks like this:
```ts
export const svgImageToString = (el: SVGSVGElement) => {
    // Serialize the SVG object, this will add an xmlns on IE
    const serialized = new XMLSerializer().serializeToString(el);
    
    // We then do convert back the SVG serialized string to new SVG 
    const parser = new DOMParser();
    const newSvg = parser.parseFromString(serialized, "image/svg+xml");
    const newSvgEl = newSvg.firstChild as SVGSVGElement;
    
    // We check if the new SVG has xmlns if not we added to it
    if(!newSvgEl.hasAttribute('xmlns')){
        newSvgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
    }

    // We serialize the new element again and return the result
    return new XMLSerializer().serializeToString(newSvgEl)
}
```

You are probably thinking why converting the SVG serialized string back to SVG object using DOMParser, due to our complex SVG's we where not able to detect and remove the double `xmlns`-tag in another way (yes we tried with regex).

Hope this will help others that will face this issue 😊

Comment if you have other alternatives to the solution! 

Cheers :)