src/scripts/utils/xml.js
'use strict';
var utilities = require('./utilityFunctions');
var xml = {};
xml.strToXMLDoc = function strToXMLDoc(stringContainingXMLSource){
//IE 8
if(typeof window.DOMParser === 'undefined'){
var xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
xmlDocument.async = false;
xmlDocument.loadXML(stringContainingXMLSource);
return xmlDocument;
}
return parseString(stringContainingXMLSource);
function parseString(stringContainingXMLSource){
var parser = new DOMParser();
var parsedDocument;
//Note: This try catch is to deal with the fact that on IE parser.parseFromString does throw an error but the rest of the browsers don't.
try {
parsedDocument = parser.parseFromString(stringContainingXMLSource, "application/xml");
if(isParseError(parsedDocument) || utilities.isEmptyString(stringContainingXMLSource)){
throw new Error();
}
}catch(e){
throw new Error("xml.strToXMLDOC: Error parsing the string: '" + stringContainingXMLSource + "'");
}
return parsedDocument;
}
function isParseError(parsedDocument) {
try { // parser and parsererrorNS could be cached on startup for efficiency
var parser = new DOMParser(),
erroneousParse = parser.parseFromString('INVALID', 'text/xml'),
parsererrorNS = erroneousParse.getElementsByTagName("parsererror")[0].namespaceURI;
if (parsererrorNS === 'http://www.w3.org/1999/xhtml') {
// In PhantomJS the parseerror element doesn't seem to have a special namespace, so we are just guessing here :(
return parsedDocument.getElementsByTagName("parsererror").length > 0;
}
return parsedDocument.getElementsByTagNameNS(parsererrorNS, 'parsererror').length > 0;
} catch (e) {
//Note on IE parseString throws an error by itself and it will never reach this code. Because it will have failed before
}
}
};
xml.parseText = function parseText (sValue) {
if (/^\s*$/.test(sValue)) { return null; }
if (/^(?:true|false)$/i.test(sValue)) { return sValue.toLowerCase() === "true"; }
if (isFinite(sValue)) { return parseFloat(sValue); }
if (utilities.isISO8601(sValue)) { return new Date(sValue); }
return sValue.trim();
};
xml.JXONTree = function JXONTree (oXMLParent) {
var parseText = xml.parseText;
//The document object is an especial object that it may miss some functions or attrs depending on the browser.
//To prevent this problem with create the JXONTree using the root childNode which is a fully fleshed node on all supported
//browsers.
if(oXMLParent.documentElement){
return new xml.JXONTree(oXMLParent.documentElement);
}
if (oXMLParent.hasChildNodes()) {
var sCollectedTxt = "";
for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) {
oNode = oXMLParent.childNodes.item(nItem);
/*jshint bitwise: false*/
if ((oNode.nodeType - 1 | 1) === 3) { sCollectedTxt += oNode.nodeType === 3 ? oNode.nodeValue.trim() : oNode.nodeValue; }
else if (oNode.nodeType === 1 && !oNode.prefix) {
sProp = utilities.decapitalize(oNode.nodeName);
vContent = new xml.JXONTree(oNode);
if (this.hasOwnProperty(sProp)) {
if (this[sProp].constructor !== Array) { this[sProp] = [this[sProp]]; }
this[sProp].push(vContent);
} else { this[sProp] = vContent; }
}
}
if (sCollectedTxt) { this.keyValue = parseText(sCollectedTxt); }
}
//IE8 Stupid fix
var hasAttr = typeof oXMLParent.hasAttributes === 'undefined'? oXMLParent.attributes.length > 0: oXMLParent.hasAttributes();
if (hasAttr) {
var oAttrib;
for (var nAttrib = 0; nAttrib < oXMLParent.attributes.length; nAttrib++) {
oAttrib = oXMLParent.attributes.item(nAttrib);
this["@" + utilities.decapitalize(oAttrib.name)] = parseText(oAttrib.value.trim());
}
}
};
xml.JXONTree.prototype.attr = function(attr) {
return this['@' + utilities.decapitalize(attr)];
};
xml.toJXONTree = function toJXONTree(xmlString){
var xmlDoc = xml.strToXMLDoc(xmlString);
return new xml.JXONTree(xmlDoc);
};
/**
* Helper function to extract the keyvalue of a JXONTree obj
*
* @param xmlObj {JXONTree}
* return the key value or undefined;
*/
xml.keyValue = function getKeyValue(xmlObj) {
if(xmlObj){
return xmlObj.keyValue;
}
return undefined;
};
xml.attr = function getAttrValue(xmlObj, attr) {
if(xmlObj) {
return xmlObj['@' + utilities.decapitalize(attr)];
}
return undefined;
};
xml.encode = function encodeXML(str) {
if (!utilities.isString(str)) return undefined;
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
xml.decode = function decodeXML(str) {
if (!utilities.isString(str)) return undefined;
return str.replace(/'/g, "'")
.replace(/"/g, '"')
.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&');
};
module.exports = xml;