Before using this code, check if your browser has native support for Node.baseURI.
These two functions aim to allow some support for xml:base.
Note however, that this code is not based on a thorough examination of the specs related to forming base URIs and could well have a number of errors. However, it is working in some of the cases tested.
var scheme = /(\w(\w|\d|\+|\- |\ .)*)\:\/\//;
function getXmlBaseLink (xlink, thisitem) {
var xmlbase = '';
if (!xlink.match(scheme)) { // Only check for XML Base if there is no protocol // tests for 'scheme' per http://www.ietf.org/rfc/rfc2396.txt'
xmlbase = getXmlBase (thisitem);
if (!xmlbase.match(/\/$/) && !xlink.match(/\/$/)) { // If no preceding slash on XLink or trailing slash on xml:base, add one in between
xmlbase += '/';
}
else if (xmlbase.match(/\/$/) && xlink.match(/\/$/)) {
xmlbase = xmlbase.substring(0, xmlbase.length-2); // Strip off last slash to join with XLink path with slash
}
// alert(xmlbase + '::' + xlink);
}
var link = xmlbase + xlink;
if (!link.match(scheme)) { // If there is no domain, we'll need to use the current domain
var loc = window.location;
if (link.indexOf('/') === 0 ) { // If link is an absolute URL, it should be from the host only
link = loc.protocol + '//' + loc.host + link;
}
else { // If link is relative, it should be from full path, minus the file
var dirpath = loc.pathname.substring(0, loc.pathname.lastIndexOf('/')-1);
if (link.lastIndexOf('/') !== link.length-1) {
link += '/';
}
link = loc.protocol + '//' + loc.host + dirpath + link;
}
}
return link;
}
function getXmlBase (thisitem) {
// Fix: Need to keep going up the chain if still a relative URL!!!!!
// var ns = 'http://www.w3.org/XML/1998/namespace';
var att, protocolPos;
var xmlbase = '';
var abs = false;
// Avoid loop if node is not present
if (!thisitem || !thisitem.nodeName) {
return xmlbase;
}
// CHECK PRESENT ELEMENT AND HIGHER UP FOR XML:BASE
// Now check for the next matching local name up in the hierarchy (until the document root)
while (thisitem.nodeName !== '#document' && thisitem.nodeName !== '#document-fragment') {
att = thisitem.getAttribute('xml:base'); // xml: namespaces MUST use 'xml' prefix
if (att) {
protocolPos = att.indexOf('//');
var protocolMatch = att.match(scheme);
if (protocolMatch) { // if has protocol, can stop
if (abs) {
var skipfile = (att.indexOf('///') === protocolPos) ? 3 : 2; // If the file protocol has an extra slashe, prepare to also skip it in the separator search
var att2 = att.indexOf('/', protocolPos+skipfile); // Find first path separator ('/') after protocol
if (att2 !== -1) {
att = att.substring(0, att2 - 1); // Don't want any trailing slash, as the absolute path to be added already has one
}
}
else if (!att.match(/\/$/)) { // If no trailing slash, add one, since it is being attached to a relative path
att += '/';
}
xmlbase = att + xmlbase; // If previous path was not absolute, resolve against the full URI here'
break;
}
else if (att.indexOf('/') === 0) { // if absolute (/), need to prepare for next time to strip out after slash
xmlbase = att + xmlbase;
abs = true; // Once the protocol is found on the next round, make sure any extra path is ignored
}
else { // if relative, just add it
xmlbase = att + xmlbase;
}
}
thisitem = thisitem.parentNode;
}
//return (xmlbase === '') ? null : xmlbase;
return xmlbase;
}
