You seem to be confused on how the namespaced elements and attributes do work.
In your inlined markup, you'll indeed add either an xmlns attribute to the root element, or an namespace header to your namespaced attributes (e.g xlink:) after you've defined its namespaceURI as an attribute on the root element.
This is necessary for the browser to be able to understand that these are namespaced, otherwise, it will try to parse it with the document's namespaceURI (by default, "http://www.w3.org/1999/xhtml" in html document)
But, since you're dealing with javascript, these namespaceURIs need to be set at creation of the element, or of the attribute.
For this, you use document.createElementNS(namespaceURI, elementName), and element.setAttributeNS(namespaceURI, attrName, attrValue), or even document.createAttributeNS(...).
Because you've set it in js, and that the browser doesn't need to actually write it in the markup, you'll not see the xmlns attribute nor xlink: NSheader in your inspector, but they're here.
You can just call the outerHTML property of your element to convince yourself, and btw, a better way to get a string representation of the DOM is to use an XMLSerializer and it's serializeToString(elem) method.
console.log("document's namespaceURI :",document.documentElement.namespaceURI)
// we're in an html document,
// this means that all 'createElement(xxx)' will correspond to
// 'document.createElementNS('http://www.w3.org/1999/xhtml', xxx)'
// our two namespace URIs
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
// There is also an HTMLSVGElement
//but since you seem to want to make a standaone svg document from this node,
// you have to use the NS version
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// this is an xlink attribute
// note that you should not set the 'xlink:' header, the browser already know its namespace
a.setAttributeNS(xlinkNS, 'href', 'http://stackoverflow.com');
// an other SVG element
var r = document.createElementNS(svgNS, 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
// here we see that the 'xlink:' header is actually set,
// but it forgets the namespace URI declarations in some UAs (at least in FF...).
console.log("outerHTML :", svgRoot.outerHTML);
// so better use an XMLSerializer :
console.log("serialized :", new XMLSerializer().serializeToString(svgRoot));
And getAttribute works the same way : non-NS version will use the namespace of the document calling it.
Now, for the why you can call setAttributeNS(nameSpaceURI, 'namespace:attr', val), but can't call getAttributeNS(nameSpaceURI, 'namespace:attr')`, it's because browsers are kind enough to correct you, in this particular case.
You can see that calling setAttribute('xlink:href', value) will create an other attribute than the one set by the NS version, and that setting an href attribute with a lambda header will just overwrite the one without this header. The only reason to set this header here is to control the name of the namespace when serializing the node to a string ; browsers will have different default values, but this xlink name is just a convention, it can actually be whatever you want.
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// browsers should keep it but don't set it as the actual link target
a.setAttribute('xlink:href', 'http://noHeader.com');
// same here
a.setAttribute('href', 'http://noNameSpace.com');
// this one is correct
a.setAttributeNS(xlinkNS, 'href', 'http://xlinkNoHeader.com');
// but this will overwrite the previous one without the header
a.setAttributeNS(xlinkNS, 'other:href', 'http://xlinkOtherHeader.com');
var r = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
for (var i = 0; i < a.attributes.length; i++) {
console.log(a.attributes[i].name, a.attributes[i].textContent, a.attributes[i].namespaceURI);
}
But if you try this on Chrome, you may see that the one attribute actually retained is the one without namespace. This is a bug.
getAttributeNS;getAttributeshould work just fine;getAttributeNSat all?