javascriptsvgdomnamespacesxml-namespaces

Render SVG string to DOM via DOMParser SVG namespace


I'm trying to parse a SVG element from a string and render it into the DOM but when I parse as image/svg+xml, the <svg> gets appended into the DOM in some strange way that does not render it (at least in Firefox). When I parse as text/html, it does render but adds an undesired xmlns attribute.

Is there some way to still parse as image/svg+xml (because that's what it is) while having it render? I tried document.adoptNode but it did not help.

This does not render:

const svg = '<svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.75 2a.75.75 0 0 1 .75.75V7h4.25a.75.75 0 1 1 0 1.5H8.5v4.25a.75.75 0 1 1-1.5 0V8.5H2.75a.75.75 0 0 1 0-1.5H7V2.75A.75.75 0 0 1 7.75 2z"/></svg>';
const parser = new DOMParser();
const doc = parser.parseFromString(svg, 'image/svg+xml');
document.body.appendChild(doc.documentElement);

This renders, but includes undesired xmlns attribute:

const svg = '<svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.75 2a.75.75 0 0 1 .75.75V7h4.25a.75.75 0 1 1 0 1.5H8.5v4.25a.75.75 0 1 1-1.5 0V8.5H2.75a.75.75 0 0 1 0-1.5H7V2.75A.75.75 0 0 1 7.75 2z"/></svg>';
const parser = new DOMParser();
const doc = parser.parseFromString(svg, 'text/html');
document.body.appendChild(doc.body.firstChild);


Solution

  • The DOMParser() interface has a method parseFromString(string, mimeType) which parses a string containing either HTML or XML & returns an HTMLDocument or an XMLDocument.

    The second parameter mimeType determines whether to use XML parser or the HTML parser. Only text/html will invoke the HTML parser, and any other valid MIME type will invoke the XML parser refer

    So, it will work as :

    const svg = '<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg"><circle r="45" cx="50" cy="50" fill="grey" /></svg> ';
    const parser = new DOMParser();
    const doc = parser.parseFromString(svg, 'image/svg+xml');
    const svgImg = doc.querySelector("svg")
    document.body.appendChild(svgImg);
    <html>
      <body>
        <h2>Parsing SVG using DOMParser()</h2>
      </body>
    </html>