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 https://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 = 'https://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; }