HTML Entities in SVG Data URLs

HTML entities like   and & are tolerated in SVG when embedded directly in an HTML page. The same entities fail to render under the more strict constraints of a data URL. We demonstrate the problem and a workaround using a carefully constructed DOCTYPE declaration.

In the frame below we can view the results. The first example is the SVG embedded in HTML. Second example shows a broken image with the same SVG in a data URL. Third example shows a working image using our SVG, prefixed with the doctype and base64 encoded.

// HEIGHT 500


We begin with a simple SVG document with a <text> element containing HTML entities.

let svg = `<svg version="1.1" xmlns="" xmlns:xlink="" viewBox="0 0 200 100"> <text x="0" y="75" transform="rotate(-20)">This&nbsp;&amp;&nbsp;That</text> <circle fill="lightblue" cx="150" cy="50" r="30" /> </svg>` let result = document.createElement("div") result.innerHTML = svg

The &nbsp; and &amp; expressions work fine when the SVG document is embedded within an HTML document. But they break when we try to create a Data URL.

let broken = document.createElement("img") broken.setAttribute("width", "100%") broken.setAttribute("height", "70px") broken.setAttribute("src",`data:image/svg+xml,${svg}`) result.appendChild(broken)

Declaring the entities in a DOCTYPE and encoding with base64 does what we want.

let entities = `<!ENTITY amp "&#38;"> <!ENTITY nbsp "&#160;">` let doctype = `<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "" [${entities}]>` let fixed = document.createElement("img") fixed.setAttribute("width", "100%") fixed.setAttribute( "src", `data:image/svg+xml;base64,${btoa(doctype+svg)}`) result.appendChild(fixed)

We export the markup for the interpreter in the frame.

export default result.innerHTML