1

In HTML5/JavaScript, if I create a namespaced dom node programmatically, like so:

svgElt = document.createElementNS("http://www.w3.org/2000/svg", 'svg')

the node 'knows' it's own namespace, which I can retrieve like so:

svgElt.namespaceURI // result: "http://www.w3.org/2000/svg"

But the namespace is not treated as a "normal" attribute:

svgElt.getAttribute('xmlns') // result: null

So the behavior of the programmatically created node is different from the equivalent "straight" node

<svg xmlns="http://www.w3.org/2000/svg" id="mySVG"></svg>

for which .getAttribute works:

document.getElementById('mySVG').getAttribute('xmlns') // result: "http://www.w3.org/2000/svg"

That is a potential problem when I use .outerHTML and need namespace information contained in the result. The namespace info might be lost for the programmatically created nodes, and I might have to add it manually; and this seems like a thing "I shouldn't have to care about" - thus the question.

An example where you need .outerHTML with namespace info in it is (see this question, Hubert OG 's answer) when you want to convert an inline SVG node into an Image by setting the image source to a data url , as in

'data:image/svg+xml,' + your_svg_element.outerHTML

What I do is

svgNode.setAttribute('xmlns', svgNode.namespaceURI)

SVG -> Image conversion (as I implemented it) doesn't work without this trick; see also my answer to the question linked above.

Is there a better / more elegant way to do this? What is the objective of svgElt.getAttribute('xmlns') returning null? Flaw or feature?

4
  • I'm talking about the mime type of the document Commented May 31, 2020 at 11:52
  • @RobertLongson: Sure. So are you saying, the result of calling .outerHTML on some dom node will change if I change the mime type I serve the document with, did I understand you correctly? Commented May 31, 2020 at 19:36
  • 1
    @mathheadinclouds - Yes it can do. The mime type they're served with results in either an HTML Document or an XML Document being constructed. You can also create either type of document in JavaScript. Reading .outerHTML differs depending on the type of document. The difference between the algorithms for both types is described in the DOM Parsing and Serialization spec.
    – Alohci
    Commented May 31, 2020 at 22:16
  • 1
    FWIW, the separation of attribute and namespaceUri problem you describe goes back to the compromises that were made at the very origins of DOM, and have ever since been a source of frustration and confusion. Other object model APIs fixing this and some similar problems have been tried and used elsewhere, but for JS in browsers, DOM has endured. Backward compatibility limitations mean that the quirky behaviour must remain.
    – Alohci
    Commented May 31, 2020 at 22:17

2 Answers 2

1

You can simply use an XMLSerializer for this, which will stringify your DOM tree to xml and thus preserve the namespaces.

const svgElt = document.createElementNS("http://www.w3.org/2000/svg", 'svg')
const serialized = new XMLSerializer().serializeToString(svgElt);
console.log(serialized);

0

Please read the comments under question first.

Here is how we get html with namespace info by "xhtml-ifying" the dom node, and then calling .outerHTML, which will then be xhtml (and have the namespace info the html is lacking).

function outerXHTML(node){
    var nsx = "http://www.w3.org/1999/xhtml";
    var xdoc = document.implementation.createDocument(nsx, 'html');
    xdoc.documentElement.appendChild(node);
    return node.outerHTML;
}
function innerXHTML(node){
    var nsx = "http://www.w3.org/1999/xhtml";
    var xdoc = document.implementation.createDocument(nsx, 'html');
    xdoc.documentElement.appendChild(node);
    return node.innerHTML;
}

(clone node first if it should remain in original document.)

related question (x/html conversion)

related question (document creation)

fiddle for testing the html to xhtml conversion

test Kaiido version with arbitrary HTML string from textbox

Not the answer you're looking for? Browse other questions tagged or ask your own question.