﻿JSOM = function(xml, errorHandler){
	var result = {};
	var doc = JSOM.parse(xml, errorHandler);
	JSOM.buildObject(JSOM.getRootNode(doc), result);
	delete doc;
	return result;
}

JSOM.attributePrefix = "$";

JSOM.hasMoreElements = function(node){
	if(!node || !(node.firstChild) || node.firstChild.hasChildNodes == null) return false;
	var hasChildren=false;
	for (var i = 0; i < node.childNodes.length; i++) {
		if (node.childNodes[i].nodeType != 3) {
			hasChildren = true;
		}
	}
	return hasChildren;	
}

JSOM.setAttributes = function(result, node){
	var attributes = node.attributes;
	
	if(attributes){
		for(var i=0; i<attributes.length; i++){
			result[JSOM.attributePrefix + attributes[i].name] = attributes[i].value;
		}
	}
}

JSOM.buildObject = function(node, result){
	if (typeof result == "undefined") {
		result = {};
	}

	JSOM.setAttributes(result, node);
	var children = node.childNodes;
	for(var i=0; i<children.length;i++){
		var currentNode=children[i];
		if(JSOM.hasMoreElements(currentNode)){
			JSOM.setValue(result, currentNode.nodeName, JSOM.buildObject(currentNode));
		}
		else if (currentNode.nodeType == 1){
			var val = JSOM.getValue(currentNode);
			JSOM.setValue(result, currentNode.nodeName, val == null ? {isEmpty: true} : new String(val));
		}
	}
	return result;
}

JSOM.setValue = function (result, nodeName, value){
	if (typeof result[nodeName] == "undefined") {
		result[nodeName] = value;
	} else {
		if (!Object.isArray(result[nodeName])) {
			result[nodeName] = [result[nodeName]];
		}
		result[nodeName].push(value);
	}
}

JSOM.isArray = function(object) {
	if (Object.isArray) {
		return Object.isArray(object);
	} else if (isArray) {
		return isArray(object);
	}
    return object != null && typeof object == "object" &&
      'splice' in object && 'join' in object;
}

JSOM.getRootNode = function(doc){
	
	if(window.ActiveXObject){
		return doc.documentElement;
	}
	else{
		if(doc.childNodes.length == 0 || doc.firstChild == null) return null;
		var currentNode = doc.firstChild;
		if(currentNode.nodeType == 1){
			return currentNode;
		} else {
			for(;currentNode && currentNode.nodeType != 1;){
				currentNode = currentNode.nextSibling
				if(currentNode.nodeType == 1){
					return currentNode;
				}
			}		
		}
	}
	return null;
}

JSOM.getValue = function(node){
	if(node == null) return null;
	if(node.childNodes.length > 0){
		for(var i=0; i < node.childNodes.length; i++){
			var child = node.childNodes[i];
			if(child.nodeType == 3){
				return child.nodeValue;
			}
		}
	}
	return null;	
}

JSOM.parse = function(xml, errorHandler)
{
	var xmlDoc = null;
	try
	{
		//Internet Explorer
		if(window.ActiveXObject){
			xmlDoc= JSOM.MSXML("Microsoft.XMLDOM");
			xmlDoc.async=false;
			xmlDoc.loadXML(xml);
		} else {  //Firefox, Mozilla, Opera, etc.
			parser=new DOMParser();
			xmlDoc=parser.parseFromString(xml,"text/xml");
		}
	}
	catch(e) {
		if (typeof errorHandler != "undefined") {
			errorHandler(window.ActiveXObject ? e.Message : e);
		}
	}
	return xmlDoc;
}

JSOM.MSXML = function(){
	var versions = ["MSXML2.DOMDocument.6.0",
			"MSXML2.DOMDocument.5.0",
			"MSXML2.DOMDocument.4.0",
			"MSXML2.DOMDocument.3.0",
			"MSXML2.DOMDocument",
			"Microsoft.XmlDom"];
	
	for(var i = 0; i < versions.length; i++){
		try{
			var xmldom = new ActiveXObject(versions[i]);
			if(xmldom){
				return xmldom;
			}
		} catch(e){};
	}
	throw new Error("MSXML is not installed.");
}
