Bw.Xml = {};

Bw.Xml.Path = 
{
	cache: {},
	
	compile: function (path)
	{
		var code = "var n=r;";
		var start = 0;
		var end = false;
		
		while (!end)
		{
			var stop = path.indexOf('/', start);
			if (stop == -1) {
				stop = path.length;
				end = true;
			}
			
			var e = path.substring (start, stop);

			var a = null;
			var p = e.indexOf ('@');
			if (p != -1) {
				a = e.substring (p+1, e.length);
				e = e.substring (0, p);
			}

			var i = 0;
			var bo = e.indexOf ('[');
			if (bo != -1) 
			{
				var bc = e.indexOf (']', bo);
				if (bc != -1)
				{
					i = e.substring (bo+1,bc);
					e = e.substring (0,bo);
				}
			}
			
			if (e != "" || i != 0) {
				code=code+("n=Bw.Xml.Path._el(n,'"+e+"',"+i+",c);");
			}
			
			if (a != null && end) {
				code=code+("n=Bw.Xml.Path._at(n,'"+a+"',c);");
			}

			start=stop+1;
		}
		
		return new Function("r","c",code+"return n;");
	},
	
	navigate: function (path, root, create)
	{
		var c = Bw.Xml.Path.cache[path];
		if (!c || c == null) {
			c = Bw.Xml.Path.compile (path);
			Bw.Xml.Path.cache[path] = c;
		}
	
		return c(root,create);
	},

	_el: function (node, name, index, create)
	{	
		if (node == null) return null;
		if (name == '.' || name == '') return node;
		
		function arr (parent, name)
		{
			var n = [];
			var i = 0;
			var c = parent.firstChild;
			while (c != null)
			{
				if (c.nodeType == 1 && c.nodeName == name) n[i++] = c;
				c = c.nextSibling;
			}
			return n;
		};
	
		var nodes = arr (node, name);
		var l = nodes.length;

		if (index < l) return nodes[index];
		if (!create) return null;
		
		var gap = index - l + 1;
		var doc = node.ownerDocument;
		var n = null;
		for (var j = 0; j < gap; j++)
		{
			n = doc.createElement (name);
			node.appendChild (n);
		}
		
		return n;
	},

	_at: function (node, name, create)
	{	
		if (node == null) return null;
		var a = node.getAttributeNode (name);
		if (a != null || (a == null && !create)) {
			return a;
		}
		node.setAttribute (name, "");
		return node.getAttributeNode (name);
	}
};


Bw.Xml.Helpers = 
{
	getNodes: function (node, path)
	{
		var a = [];
		var n = Bw.Xml.Path.navigate (path, node, false);
		var c = n;
		while (c != null)
		{
			if (c.nodeName == n.nodeName) {
				a.push (c);
			}
			c = c.nextSibling;
		}
		
		return a;
	},

	getNode: function (node, path, create)
	{
		var tmp = Bw.Xml.Path.navigate (path, node, create);
		return tmp;
	},

	getNodeValue: function (node)
	{
		var c = node.childNodes;
		var l = c.length;
		var v = "";
		for (var i = 0; i < l; i++)
		{
			var n = c[i];
			var t = n.nodeType;
			if (t == 3 || t == 4) {
				v += n.nodeValue;
			}
		}
		
		return v;
	},

	setNodeValue: function (node, value)
	{
		if (!value) return;
		
		if (node.nodeType == 2)
		{
			node.value = value;
			return;
		}
		
		var c = node.childNodes;
		var l = c.length;
		for (var i = 0; i < l; i++)
		{
			var n = c[i];
			if (n.nodeType == 3)
			{
				if (value != null) n.data = value;
				else node.removeChild (n);
				return;
			}
		}
		
		if (value != null)
		{
			var f = node.firstChild;
			var t = node.ownerDocument.createTextNode (value);
			if (f == null) {
				node.appendChild (t);
			} else {
				node.insertBefore (t, f);
			}
		}
	},
	
	removeNode: function (node)
	{
		var n = node;
		if (n.nodeType == 2) {
			n.ownerElement.removeAttributeNode (n);
		} else {
			n.parentNode.removeChild (n);
		}
		return n;
	},

	importNode: function (dom, node, deep)
	{
		var n;

		if (node.nodeType == 1)
		{
			n = dom.createElement (node.nodeName);
			for (var i = 0; i < node.attributes.length; i++)
			{
				var attr = node.attributes[i];
				if (attr.nodeValue != null && attr.nodeValue != '')
				{
					n.setAttribute (attr.name, attr.nodeValue);
				}
			}
			
		}
		else if (node.nodeType == 3)
		{
			n = dom.createTextNode (node.nodeValue);
		}

		if (deep && node.hasChildNodes())
		{
			for (var i = 0; i < node.childNodes.length; i++) 
			{
				n.appendChild (Bw.Xml.Helpers.importNode (dom, node.childNodes[i], true));
			}
		}

		return n;
	},

	createDocument: function ()
	{
		var i = document.implementation;
		var d = (i.createDocument) ? i.createDocument ("","",null) : new ActiveXObject ("MSXML.DOMDocument");

		return d;
	},
	
	createHttpRequest: function ()
	{
		return (typeof ActiveXObject != "undefined") ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
	}
};


