function garden(){
	this.tree = null;
	
	//Function: Write xmlCode to xmlFile.
	//NOTE: Include this code somewhere in the <body> of the page.
	//<form target="_blank" method="post" id="xmlForm" action="postXML.cfm">
	//<input type="hidden" name="xmlPath" value="../advert" />
	//<input type="hidden" name="xmlFile" />
	//<input type="hidden" name="xmlString" />
	//</form>
	this.publish = function(xmlFileName){
		frm = document.forms["xmlForm"];
		frm.xmlString.value = this.toString();
		frm.xmlFile.value = xmlFileName;
		frm.submit();		
	}
	
	this.recordpublish = function(xmlFileName,record,rName,rID){
		
		//TODO: by id
		temp.remTAG(temp.tree.documentElement,temp.getTAG(temp.tree.documentElement,rName,rID));
		temp.tree.documentElement.appendChild(record);
		frm.xmlString.value = temp.toString();
		frm.xmlFile.value = xmlFileName;
		frm.submit();
	}

	//Will remove this
	//Special formatting for some XML -esp in forms that are dynamically created via javascript
	//this.strXML = function(val){ return strReplace(val,"'","&#39;"); }	

	//returns the number of tags with the name given	
	this.getLEN = function(obj,tag){ return (obj ? obj.getElementsByTagName(tag).length : 0); }
	//returns the specified tag
	this.getTAG = function(obj,nm,i){ return (obj ? obj.getElementsByTagName(nm)[i] : null); }
	//If the tag exists, return it, otherwise create a temporary one (w/o attatching it)
	this.creTAG = function(obj,nm,i){
		tag = this.getTAG(obj,nm,i);
		return (tag ? tag : this.tree.createElement(nm) );
	}
	//If the tag exists, remove it. Add a new tag to the XML file
	this.clrTAG = function(obj,nm,i){
		tag = this.getTAG(obj,nm,i);
		if (tag){ this.remTAG(obj,tag); }
		return this.addTAG(obj,nm);
	}
	//add a new tag to an object from a document
	this.addTAG = function(obj,tag){
		thisTAG = this.tree.createElement(tag);
		obj.appendChild(thisTAG);
		return thisTAG;	
	}
	//check if a tag exists
	this.hasTAG = function(obj,nm){ return ( obj && obj.getElementsByTagName(nm).length > 0 ? true : false ); }
	//remove a tag
	this.remTAG = function(obj,tag){ if (tag != null){ obj.removeChild(tag); } }
	//get all tags with a specific name
	this.getALL = function(obj,tag){
		return obj.getElementsByTagName(tag);
		//tlist = obj.getElementsByTagName(tag);
		//var tmpList = new Array();
		//for (i = 0; i < tlist.length; i++){ tmpList[i] = tlist[i]; }
		//alert("TMP LIST: "+tmpList);
		//return tmpList;

	}
	//get the text inside a tag
	this.getVAL = function(tag){ return (tag && tag.firstChild ? tag.firstChild.nodeValue : null ); }
	//set the value of a tag
	this.setVAL = function(tag,val){
		if (tag.firstChild){ tag.firstChild.nodeValue = val; }
		else { tag.appendChild(this.tree.createTextNode(val)); }
	}
	//get the text of an attribute
	this.getATT = function(tag,att){ return (tag ? tag.getAttribute(att) : null); }
	//check if an attribute exists
	this.hasATT = function(tag,att){ return (tag.hasAttribute(att) ? true : false ); }
	//set an attribute
	this.setATT = function(tag,att,val){ tag.setAttribute(att,val); }
	//remove an attribute
	this.remATT = function(tag,att){ tag.removeAttribute(att); }
	
	//convert an XML object to the equivalent code string
	this.toString = function(){ return (new XMLSerializer()).serializeToString(this.tree); }
	
	//load an XML file (w/ sarissa)		
	this.load = function(filename){
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("GET", filename, false);
		xmlhttp.send('');
		this.tree = xmlhttp.responseXML
		this.tree.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
		this.tree.setProperty("SelectionLanguage", "XPath");
	}
	
	//xpath expressions
	this.xpSingle = function(thisNode,expr){ return thisNode.selectSingleNode(expr); }
	this.xpAll = function(thisNode,expr){
		tlist = thisNode.selectNodes(expr); 
		var tmpList = new Array();
		for (i = 0; i < tlist.length; i++){ tmpList[i] = tlist[i]; }
		return tmpList;
	}
}

//Replace findText with replaceText (irrelevant of case).
//(NOTE: replaceText may contain findText without resulting errors).
function strReplace(originalString,findText,replaceText){
	findText = findText.toLowerCase();
	var findString = originalString.toLowerCase();
	var pos = findString.indexOf(findText);
	
	if (pos != -1){
		return	originalString.substring(0,pos)
				+replaceText
				+strReplace(originalString.substring( pos+findText.length, originalString.length ), findText, replaceText );
	} else { return originalString; }	
}	