// XMLNode
function XMLNode(input_obj)
{
	this.xml_obj = input_obj;
}

XMLNode.prototype.getNodeName = function()
{
	return this.xml_obj.nodeName;
}

XMLNode.prototype.getNodeValue = function()
{
	if (this.xml_obj.firstChild != null && this.xml_obj.firstChild.data != null)
	{
		return this.xml_obj.firstChild.data;
	}
	return "";
}

XMLNode.prototype.setNodeValue = function(input_str)
{
	if (input_str == null)
	{
		input_str = "test";
	}
	if (this.xml_obj.childNodes.length == 0)
	{
		var document_obj = this.xml_obj.ownerDocument;
		var text_obj = document_obj.createTextNode(input_str);
		this.xml_obj.appendChild(text_obj);
		return;
	}
	if (this.xml_obj.firstChild.nodeType != 3)
	{
		return;
	}
	if (this.xml_obj.firstChild != null && this.xml_obj.firstChild.data != null)
	{
		this.xml_obj.firstChild.data = input_str;
	}
}

XMLNode.prototype.getAttributes = function(name_str)
{
	var attribute_obj = new Object();
	if (this.xml_obj.attributes.length == 0)
	{
		return null;
	}
	for (var i = 0; i < this.xml_obj.attributes.length; i++)
	{
		if (name_str != null && this.xml_obj.attributes[i].name == name_str)
		{
			return this.xml_obj.attributes[i].value;
		}
		attribute_obj[this.xml_obj.attributes[i].name] = this.xml_obj.attributes[i].value;
		if (i == this.xml_obj.attributes.length - 1 && name_str != null)
		{
			return null;
		}
	}
	return attribute_obj;
}

XMLNode.prototype.setAttribute = function(name_str, value_str)
{
	if (this.getAttributes(name_str) != null)
	{
		for (var i = 0; i < this.xml_obj.attributes.length; i++)
		{
			if (this.xml_obj.attributes[i].name == name_str)
			{
				this.xml_obj.attributes[i].value = value_str;
				break;
			}
		}
	}
	else
	{
		var document_obj = this.xml_obj.ownerDocument;
		var attribute_obj = document_obj.createAttribute(name_str);
		attribute_obj.value = value_str;
		this.xml_obj.setAttributeNode(attribute_obj);
	}
}

XMLNode.prototype.removeAttribute = function(name_str)
{
	for (var i = 0; i < this.xml_obj.attributes.length; i++)
	{
		if (this.xml_obj.attributes[i].name == name_str)
		{
			this.xml_obj.removeAttributeNode(this.xml_obj.attributes[i]);
			return;
		}
	}
}

XMLNode.prototype.getParentNode = function()
{
	if (this.xml_obj.parentNode != null)
	{
		return new XMLNode(this.xml_obj.parentNode);
	}
	return null;
}

XMLNode.prototype.getChildNodes = function()
{
	var child_array = new Array();
	if (this.xml_obj.childNodes != null)
	{
		for (var i = 0; i < this.xml_obj.childNodes.length; i++)
		{
			child_array.push(new XMLNode(this.xml_obj.childNodes[i]));
		}
	}
	return child_array;
}

XMLNode.prototype.getFirstChild = function()
{
	if (this.xml_obj.firstChild != null)
	{
		return new XMLNode(this.xml_obj.firstChild);
	}
	return null;
}

XMLNode.prototype.getLastChild = function()
{
	if (this.xml_obj.lastChild != null)
	{
		return new XMLNode(this.xml_obj.lastChild);
	}
	return null;
}

XMLNode.prototype.getNextSibling = function()
{
	if (this.xml_obj.nextSibling != null)
	{
		return new XMLNode(this.xml_obj.nextSibling);
	}
	return null;
}

XMLNode.prototype.getPreviousSibling = function()
{
	if (this.xml_obj.previousSibling != null)
	{
		return new XMLNode(this.xml_obj.previousSibling);
	}
	return null;
}

XMLNode.prototype.appendChild = function(input_node)
{
	this.xml_obj.appendChild(input_node.xml_obj);
	return input_node;
}

XMLNode.prototype.insertBefore = function(input_node, before_node)
{
	this.xml_obj.insertBefore(input_node.xml_obj, before_node.xml_obj);
	return input_node;
}

XMLNode.prototype.removeChild = function(input_node)
{
	this.xml_obj.removeChild(input_node.xml_obj);
}

XMLNode.prototype.cloneNode = function(deep_bool)
{
	return new XMLNode(this.xml_obj.cloneNode((deep_bool == true)));
}

XMLNode.prototype.getSingleNode = function(xpath_str)
{
	if (document.evaluate)
	{
		var result = document.evaluate(xpath_str, this.xml_obj, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
		if (result.singleNodeValue == null)
		{
			return null;
		}
		return new XMLNode(result.singleNodeValue);
	}
	else
	{
		try
		{
	    return new XMLNode(this.xml_obj.selectSingleNode(xpath_str));
		}
		catch(e)
		{
			throw "XPath not supported by this browser.";
			return null;
		}
	}
}

XMLNode.prototype.getNodeSet = function(xpath_str)
{
	var result_array = new Array();
	if (document.evaluate)
	{
		var result = document.evaluate(xpath_str, this.xml_obj, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		for (var i = 0; i < result.snapshotLength; i++)
		{
			result_array.push(new XMLNode(result.snapshotItem(i)));
		}
		return result_array;
	}
	else
	{
		try
		{
			var temp_array = this.xml_obj.selectNodes(xpath_str);
			for (var i = 0; i < temp_array.length; i++)
			{
				result_array.push(new XMLNode(temp_array[i]));
			}
			return result_array;
		}
		catch(e)
		{
			throw "XPath not supported by this browser.";
			return result_array;
		}
	}
}

XMLNode.prototype.toString = function()
{
	if (typeof XMLSerializer != "undefined")
	{
		return (new XMLSerializer()).serializeToString(this.xml_obj);
	}
	else if (this.xml_obj.xml != null)
	{
		return this.xml_obj.xml;
	}
	return "can't serialize xml";
}

function XML(input_str)
{
	if (input_str == null)
	{
		input_str = "<?xml version=\"1.0\" ?><root />";
	}
	if (typeof(input_str) == "string")
	{
		this.parseXML(input_str);
	}
	else
	{
		this.xml_obj = input_str;
	}
}
XML.prototype = new XMLNode();
XML.prototype.constructor = XML;
delete XML.prototype.getNodeName;
delete XML.prototype.getNodeValue;
delete XML.prototype.setNodeValue;
delete XML.prototype.getAttributes;
delete XML.prototype.setAttribute;
delete XML.prototype.removeAttribute;
delete XML.prototype.getParentNode;
delete XML.prototype.getNextSibling;
delete XML.prototype.getPreviousSibling;
delete XML.prototype.appendChild;
delete XML.prototype.insertBefore;
delete XML.prototype.cloneNode;
delete XML.prototype.removeNode;

XML.prototype.getChildNodes = function()
{
	return new Array(new XMLNode(this.xml_obj.documentElement));
}

XML.prototype.getFirstChild = function()
{
	return new XMLNode(this.xml_obj.documentElement);
}

XML.prototype.getLastChild = function()
{
	return new XMLNode(this.xml_obj.documentElement);
}

XML.prototype.parseXML = function(input_str)
{
	if (input_str == "") input_str = null;
	if (typeof ActiveXObject != "undefined")
	{
		this.xml_obj = new ActiveXObject("MSXML2.DOMDocument");
		this.xml_obj.setProperty("SelectionLanguage", "XPath");
		if (input_str != null)
		{
			this.xml_obj.loadXML(input_str);
		}
	}
	else if (input_str != null)
	{
		if (typeof DOMParser != "undefined")
		{
			this.xml_obj = (new DOMParser()).parseFromString(input_str, "application/xml");
		}
		else
		{
			var request = new XMLHttpRequest();
			request.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(input_str), false);
			request.send(null);
			this.xml_obj = request.responseXML;
		}
	}
	else
	{
		this.xml_obj = document.implementation.createDocument("", "", null);
	}
}

XML.prototype.load = function(url_str)
{
	if (url_str == "" || url_str == null) return;
	var request;
	if (window.XMLHttpRequest)
	{
		request = new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		request = new ActiveXObject("Microsoft.XMLHTTP");
	}

	var this_obj = this;
	request.onreadystatechange = function()
	{
		if (request.readyState != 4) return;
		if (request.status == 200)
		{
			this_obj.parseXML(request.responseText);
			if (this_obj.onLoad != null)
			{
				this_obj.onLoad(true);
			}
		}
		else if (this_obj.onLoad != null)
		{
			this_obj.onLoad(false);
		}
	}
	request.open("GET", url_str, true);
	request.send(null);}

XML.prototype.sendAndLoad = function(url_str, output_xml)
{
	if (url_str == "" || url_str == null) return;
	if (output_xml == null) return;

	var request;
	if (window.XMLHttpRequest)
	{
		request = new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		request = new ActiveXObject("Microsoft.XMLHTTP");
	}

	request.onreadystatechange = function()
	{
		if (request.readyState != 4) return;
		if (request.status == 200)
		{
			output_xml.parseXML(request.responseText);
			if (output_xml.onLoad != null)
			{
				output_xml.onLoad(true);
			}
		}
		else if (output_xml.onLoad != null)
		{
			output_xml.onLoad(false);
		}
	}
	request.open("POST", url_str, true);
	request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	request.send(this.toString());
}

XML.prototype.createElement = function(name_str)
{
	return new XMLNode(this.xml_obj.createElement(name_str));
}