/** Class for performing basic XML handling operations. */
var XML = {

	/**
	 * Load an XML document from a given url.
	 *
	 * @param url   Url of the XML document.
	 * @return string of the xml, or null if the XML couldn't be retrieved.
	 */
	loadDocument: function(url) {
		if (window.ActiveXObject) {
			var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async = false;
			xmlDoc.load(url);
			return xmlDoc;
		} else if (window.XMLHttpRequest) {
			var xhr = new XMLHttpRequest();
			xhr.open('GET', url, false);
			xhr.send(null);
			return xhr.responseXML;
		} else {
			return null;
		}
	},

	/**
	 * Make an object from an XML representated by a string.
	 *
	 * @param xmlText   XML string.
	 * @return XML object.
	 */
	parse: function(xmlText) {
		var doc;
		if (window.ActiveXObject) {
			doc = new ActiveXObject('Microsoft.XMLDOM');
			doc.async = false;
			doc.loadXML(xmlText);
		} else {
			var parser = new DOMParser();
			doc = parser.parseFromString(xmlText, 'text/xml');
		}
		return doc;
	},

	/**
	 * Make a string from an XML part representated by an object.
	 *
	 * @param xmlNode   Node of the XML object that needs to be converted.
	 * @return string.
	 */
	serialize: function(xmlNode) {
		try {
			return (new XMLSerializer()).serializeToString(xmlNode);
  		} catch (e) {
			return xmlNode.xml;
  		}
	},

	/**
	 * Perform an XSL transformation.
	 *
	 * @param xml   XML object.
	 * @param xsl   XSL template object.
	 * @return string of the transformation result.
	 */
	transformXSL: function(xml, xsl) {
		if (window.ActiveXObject) {
			return xml.transformNode(xsl);
		} else if (document.implementation && document.implementation.createDocument) {
			var xsltProcessor = new XSLTProcessor();
			xsltProcessor.importStylesheet(xsl);
			var resultDocument = xsltProcessor.transformToFragment(xml, document);
			return XML.serialize(resultDocument);
		}
		return false;
	},

	/**
	 * Encode or decode HTML special characters.
	 *
	 * @param text     String to be converted.
	 * @param encode   Encodes characters to entities if true, decodes entities to characters if false.
	 * @return converted string.
	 */
	convertSpecChars: function(text, encode) {
		text += '';
		if (encode == null) {
			encode = true;
		}
		var chars = ['&', '<', '>', '"', '\''];
		var entities = ['&amp;', '&lt;', '&gt;', '&quot;', '&#39;'];
		if (encode) {
			// & must be the first to be converted
			for (var i = 0; i < chars.length; i++) {
				text = text.replace(new RegExp(chars[i], 'g'), entities[i]);
			}
		} else {
			// &amp; must be the last to be converted
			for (var i = entities.length-1; i >= 0; i--) {
				text = text.replace(new RegExp(entities[i], 'g'), chars[i]);
			}
		}
		return text;
	}
};
