function Builder(url)
{
	
	//création de l'objet xmlSource destiné a recevoir l'url et l'objet domDocument du fichier xml Source
	this.xmlSource = new Object;
	
	//création des attributs de l'objet xmlSource
	this.xmlSource.url = url;
	this.xmlSource.domDoc = getXmlDoc(this.xmlSource.url);
	
	this.nodes = new Array();
	
	//Enregistrement de la function createFromXml comme méthode de la class Builder
	this.createFromXml = createFromXml;
	
	this.deleteAllChildren = deleteAllChildren;
	
	this.createElement = createElement;
	
	this.appendMyChildren = appendMyChildren;
	
	this.insertText = insertText;
	
	//Extraction de l'objet domDocument par une requete Ajax 
	function getXmlDoc(url)
	{
		
		//créatio de xhr l'objet XmlHttpRequest en fonction du navigateur
		if (window.XMLHttpRequest)
		{ 
			var xhr = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			try 
			{
				var xhr = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch(e)
			{
				var xhr = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		
		//initialisation de la variable de test de fin de procedure ajax
		ok = false;
		
		//test des états  xhr
		xhr.onreadystatechange = function()
		{
			if(xhr.readyState == 4)
			{
				if(xhr.status == 200)
				{
					//marquage de la variable de test
					ok = true;
				}
			}
		};
		
		//lancement de la requete Ajax
		xhr.open("GET", url, false);
		xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=iso-8859-1');
		xhr.send(null);
		
		//verification de l'etat de la variable de test
		if (ok)
		{
			//renvoi de l'objet domDocument une fois nettoyé 
			result = clean(xhr.responseXML);
			return result;
		}
		
		//nettoie le domDoc de tous ses noeuds texte vide
		function clean(domDoc)
		{
			//création d'un tableau contenant l'ensemble des noeuds du domDoc
			var allNodes = domDoc.getElementsByTagName('*');
			
			//parcours du tableau et test du type de noeud
			for(i=0;i<allNodes.length;i++)
			{
				var currentPreviousNode = allNodes[i].previousSibling;
				
				if(currentPreviousNode && currentPreviousNode.nodeType == 3)
				{
					//le noeud courant est transmis à la fonction del s'il est de type 3 (text)
					del(currentPreviousNode);
				}
				
				var currentNextNode = allNodes[i].nextSibling;
				
				if(currentNextNode && currentNextNode.nodeType == 3)
				{
					//le noeud courant est transmis à la fonction del s'il est de type 3 (text)
					del(currentNextNode);
				}
			}
			
			return domDoc;
		}
		
		//Supprime le noeud passé en parametre
		function del(node)
		{
			//test du contenu du contenu du noeud courant, puis suppression du noeud
			if(!node.data.replace(/\s/g,''))
			{
				node.parentNode.removeChild(node);
			}
		}
		
	}
	
	//Crée un element dans l'abre XHTML de la page depuis une source xml
	function createFromXml(bloc, parentNode, params)
	{	
		//creation d'un tableau de parametres a partir de la chaine transmise, si celle ci existe
		if(params)
		{
			parametres = new Array();
			paramsCut = params.split("&");
			for(i=0;i<paramsCut.length;i++)
			{
				valuesCut = paramsCut[i].split("=");
				parametres[valuesCut[0]] = valuesCut[1];
			}
		}
		
		//definition de blocNode, la portion du xml visé
		blocNode = this.xmlSource.domDoc.getElementsByTagName(bloc).item(0);
		
		//créatio d'un tableau contenant l'ensemble des balises du bloc visé
		var balises = new Array();
		
		// parcours du tableau et création de la balise dans le noeud parent
		// le chargement des enfants du noeud courant dans celui-ci se fait par la fonction recursive appendMyChildren
		for (var i=0;i<blocNode.childNodes.length;i++)
		{
			balises[i] = this.appendMyChildren(blocNode.childNodes[i]);
			parentNode.appendChild(balises[i]);
		}
		
		return balises;
	}
	
	//crée le sous arbre d'un noeud de maniere recursive
	function appendMyChildren(currentNode)
	{
		//distinction du type de noeud
		if(currentNode.nodeType == 1)
		{
			var newNode = document.createElement(currentNode.tagName);
		}
		
		if(currentNode.nodeType == 3)
		{	
			// creation du neoud texte vierge
			var newNode = document.createTextNode(currentNode.nodeValue);
		}
		
		//parcours des noeuds enfants et creation de ceux-ci(recursion pour les enfants de enfants etc...)
		var i=0;
		for(i=0;i<currentNode.childNodes.length;i++)
		{
			var newChild = this.appendMyChildren(currentNode.childNodes[i]);
			newNode.appendChild(newChild);
		}
		
		//creation des attributs si le noeud courant est de type 1
		var j=0;
		if(currentNode.nodeType == 1)
		{
			for(j=0;j<currentNode.attributes.length;j++)
			{	
				attribName = currentNode.attributes[j].nodeName;
				if(currentNode.attributes[j].nodeValue.substring(0,2) == "*_")
				{	
					attribValue = parametres[currentNode.attributes[j].nodeValue.substring(2)];
				}
				else
				{
					attribValue = currentNode.attributes[j].nodeValue;
				}
				
				//creation de l'expression reguliere permetant de tester l'attribut de type javascript
				jsReg = new RegExp("^js","i");
				
				//creation des attributs
				// procedure specifique en cas d'attribut de type type (input), sinon bug dans ie
				if(attribName == "type")
				{
					newNode.type = attribValue;
				}
				else if(attribName == "id")
				{
					newNode.id = attribValue;
					
					if(attribValue.substring(0,2) == "*_")
					{
						//si l'id a un marqueur variable, on affecte la bonne valeur à this.nodes
						this.nodes[parametres[attribValue.substring(2)]] = newNode;
					}
					else
					{
						//l'id n'est pas variable, on l'affecte simplement à this.nodes
						this.nodes[attribValue] = newNode;
					}
				}
				// procedure specifique en cas d'attribut de type javascript
				else if(attribName.match(jsReg))
				{
					var allString = attribValue;
					tab = allString.split('**-**');
					eval('newNode.' + tab[0] + '=function(e){' + tab[1] + '};');
				}
				//attribution simple d'un attribut quelquonque
				else
				{
					var newAttribNode = document.createAttribute(attribName);
					newAttribNode.nodeValue = attribValue;
					newNode.setAttributeNode(newAttribNode);
				}
			}
		}
		//renvoi le noeud augmenter de sa descendance
		return newNode;
	}
	
	//fonction supprimant toutes les enfants d'un noeud
	function deleteAllChildren(tab, stringParams)
	{
		//creation d'un tableau destiné a stocker les parametres recomposés
		params = new Array();
		
		//creation du tableau destiné a stocker les id des exceptions
		except = new Array();
		
		//creation de blockParams, tableau des parametres en un loc nom/valeur si stringParams contient effectiemet des parametres
		//sinon simple affectation de la valeure "" a la premiere ligne de l'array except
		if(stringParams !="")
		{
			blockParams = stringParams.split("&");
		
			//separation des noms et des valeures, puis stockage dans params
			for(i=1;i<blockParams.length;i++)
			{
				currentParam = blockParams[i].split("=");
				params[i] = {"name":currentParam[0],"value":currentParam[1]};
				if(params[i].name == "except")
				{
					except.push(params[i].value);
				}
			}
		}
		
		//creation de allChildren tableau contenant les noeuds enfant de l'element à traiter  
		allChildren = new Array();
		if(tab.childNodes != null)
		{
			allChildren = tab.childNodes;
		}
		
		//parcour du tableau des enfants puis suppression si il ne fait pas partie des exceptions prevues
		for(i=0;i<allChildren.length;i++)
		{	
			saveMe = false;
			
			for(var j=0;j<except.length;j++)
			{
				if(except[j] && allChildren.item(i).id == except[j])
				{
					saveMe = true;
				}
			}
			
			if(!saveMe)
			{
				if(this.nodes[allChildren.item(i).id])
				{
					delete this.nodes[allChildren.item(i).id];
				}
				allChildren.item(i).parentNode.removeChild(allChildren.item(i));
				i--;
			}
		}
	}
	
	//fonction creant un element dans l'arbre dom
	function createElement(container, tagName, id, textContent)
	{
		//creation d'un nouvel element node
		node = document.createElement(tagName);
		
		//cereation de l'id
		node.id = id;
		
		//creation et affectation du noeud textuel si besoin
		if(textContent)
		{
			this.insertText(node, textContent);
		}
		
		//affiliation de l'element a son container
		container.appendChild(node);
		
		//creation de l'element dans le tableau des noeuds du builder si il a un id
		if(id)
		{
			if(id!="")
			{
				this.nodes[id] = node;
			}
		}
		
		//renvoi de l'element
		return node;
	}
	
	function insertText(container, textContent)
	{
		textNode = document.createTextNode(textContent);
		container.appendChild(textNode);
	}
}
