Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    New to the CF scene
    Join Date
    Apr 2006
    Posts
    7
    Thanks
    0
    Thanked 0 Times in 0 Posts

    XML To Array script issue

    Hello All,
    I've been working on the same script for two weeks nearly every day. I have it working almost exactly as I need it to, but there are three issues that I can't seem to figure out.
    I think it's a "can't see the forest for the trees" issue, because I've been looking at it for so long. I'm hoping a pair of fresh eyes will see a glaring error or two in what I'm doing.
    What I want to do is parse an XML file and put the keys and values into a hash.
    I originally started working on this using the method I have now, then I abandoned that thinking there was a better way and used XPath. Xpath works perfect in Mozilla, but I couldn't get IE to work at all, even using xpath_dom.js by Dimitri Glazkov. So I went back to my original plan.
    The three problems are #1 erronious replication of hash keys with no data. This can be seen at work at http://d13699489.d91.digitalelite.bi...rray_cross.php. (this is most problematic in xml_Array['data']['records']['record']['children']['son']['favorite_sport'] vs. xml_Array['data']['records']['record']['children']['son']['favorite_sport2'] because of the errroneous ->['favorite_sport1']. The other places that it happens I could live with, but prefer not to.
    #2 using a different XML file, but the same script, it drops or doesn't set slices in the hash. See http://d13699489.d91.digitalelite.bi...ray_cross2.php (every 'record' should have the same keys, but only the first one is complete).
    #3 while minor compared to the other two, the first node of the root node in both XML files are //data/time-date/published/ but the script ignores "published" and puts the data xml_Array['data']['time-date'] in instead.
    The output should look like http://d13699489.d91.digitalelite.bi...illa_works.php (this is the XPath version, Mozilla Only )
    Any help would be appreciated.

    The code involved is:
    Code:
    function xmlToArray(tree) {
    	if(tree.tagName){
    		if(tree.hasChildNodes()){
    			depth++;
    			for(j=structure.length;j>=depth;j--){
    					structure.pop(); //remove extra elements
    			}
    			structure.push(tree.nodeName);
    			for(var i=0; i<tree.childNodes.length; i++){
    				var tmp_array = new Array();
    				for(k in structure){
    					tmp_array.push(structure[k]); //put this on the end of the array.
    					var array_element = eval("xml_Array['"+tmp_array.join("']['")+"']");
    					if(!array_element){ //if the element does not exist create it.
    						if(tree.childNodes.length > 1){//if the current node has children
    							var def_element = eval("xml_Array['"+tmp_array.join("']['")+"'] = new Array()")//create array element.
    						}else{ //set the value
    							eval("xml_Array['"+tmp_array.join("']['")+"'] = '"+xmlSafe(tree.childNodes[i].nodeValue)+"'");
    							break; //we found what we wanted, NEXT!
    						}
    					}else{
    						if(k + 1 > depth){//make sure that we're at the current level.
    							tmp_array2 = structure;
    							var count = 0;
    							while(eval("typeof xml_Array['"+tmp_array2.join("']['")+"'] != 'undefined'")){//other node using this name, need to increment and create a new name.
    								count++;
    								var name_test = tmp_array2.pop();//now we have to work backwards.				
    								name_test = name_test.replace(/\d+/g,''); //remove any number from the test name.
    								tmp_array2.push(name_test+count);
    							}
    						}
    					}	
    				}
    				xmlToArray(tree.childNodes[i],1);
    			}
    			depth--;
    		}
    	}else{ //not a tag, data
    		return tree.nodeValue;
    	}
    }
    xmlToArray(tree) is initially passed xmlDoc.documentElement

    Full code is in the source of the above URLs.
    Last edited by karlkittler; 04-19-2006 at 07:59 PM.

  • #2
    New to the CF scene
    Join Date
    Apr 2006
    Posts
    7
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Exclamation

    in the above post, I said I could live with the erroneous key duplication. Well as it turns out, I can't. I didn't realize it before, but this behaves differently in different browsers.
    In IE it looks like this //root/records/record/name/<data>
    //root/records/record/name1/<empty>
    In mozilla it looks like this: //data/records/record/<empty>
    //data/records1/record1/<data>
    //data/records1/record2/<empty>
    //data/records1/record2/<data>
    which as you can see would cause problems as my method to access the information has to be different for each browser.

  • #3
    New to the CF scene
    Join Date
    Apr 2006
    Posts
    7
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Since I really hate reading threads where a question is asked and you assume the person found an answer, but it was not posted, I have the answer, it works, at least in FireFox 1.5 and IE 6.

    In the near future, you'll be able to see this in action at http://mechlogs.com and http://lancasteronline.com

    Here's a working XMLtoArray page, complete:
    Code:
    <html>
    <head>
    <script type="text/javascript"><!--
    /*
    * This script is copyright Karl Kittler (karl.kittler AT gmail.com)
    * This program is free software; you may redistribute and/or modify
    * it under the terms of the GNU General Public License version 2 or
    * the GNU Lesser General Public License version 2.1 as published by
    * the Free Software Foundation.
    * should you feel so inclined, donations may be made via PayPal at
    * at the same address.
    * the above statement was included because so few people read this.
    * this text must remain in any and all future revisions.
    */
    function loadXML(file){//load xml file
    	if (window.ActiveXObject){// code for IE
    		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    		xmlDoc.async=false;
    		xmlDoc.load(file);
    		hokey_pokey();
    	}else if (document.implementation && document.implementation.createDocument){// code for Mozilla, etc.
    		xmlDoc= document.implementation.createDocument("","",null);
    		xmlDoc.load(file);
    		xmlDoc.onload=hokey_pokey;
    	}else{
    		alert('Your browser cannot handle this script');
    	}
    }
    
    function xmlToArray(tree) { //this returns the very outer part, but nothing inside it.
    	if(tree.tagName){
    		if(tree.hasChildNodes()){
    			for(var i=0; i<tree.childNodes.length; i++){
    				tmp = xmlToArray(tree.childNodes[i]);
    				if(eval("typeof return_array == 'undefined'")) var return_array = new Array();
    				var count = '';
    				while(eval("typeof return_array['" + tree.childNodes[i].tagName + count + "'] != 'undefined'")){//other node using this name, need to increment and create a new name.
    					if(count == '')count = 0;
    					count++;
    				}
    				if(tmp){
    					if(tree.childNodes[i].tagName){
    						return_array[tree.childNodes[i].tagName+count] = tmp;
    					}else{
    						return_array = tmp;
    					}
    				}
    			}
    			return return_array;
    			
    		}
    	}else{ //not a tag, data
    		return xmlSafe(tree.nodeValue);
    	}
    }
    
    function xmlSafe(string){
    	if(string == '' || string == null) return '';
    	search_array = Array();
    	//first, convert all existing HTMLEntities preceeding ampersand to something, so we don't screw them up.
    	string = string.replace( /&([a-zA-Z]{3,6})/g, "AMPERSAMD$1");
    	search_array['&'] = '&amp;';
    	search_array['"'] = '&quot;';
    	search_array["'"] = '&apos;';
    	search_array['<'] = '&lt;';
    	search_array['>'] = '&gt;';
    	//remove retuns and new lines
    	search_array['[\r\n]'] = '';
    	//now, put all the ampersands back in the encoded chars
    	search_array['AMPERSAMD'] = '&';
    	for(f in search_array){
    		var re = new RegExp (f, 'gi') ;
    	    string = string.replace( re, search_array[f]);
    	}
    	/*string = string.replace(/&/g,'&amp;');
    	string = string.replace(/"/g,'&quot;');
    	string = string.replace(/'/g,'&apos;');
    	string = string.replace(/</g,'&lt;');
    	string = string.replace(/>/g,'&gt;');
    	*/
    	return string;
    }
    
    function arrayToList(obj,name,recursing){ //this works fine, don't mess with it.
    	//If it doesn't work, it's your data, not me.
    	tmp = '';
    	if(!name) name='';
    	if(recursing) tmp = '<ul><li>(array)['+name+'=>';
    	if(obj.constructor == Array){
    		for(var k in obj){
    			tmp += arrayToList(obj[k],k.toString(),1);
    		}
    		
    	}else{
    		tmp += '"'+obj+'"';
    	}
    	if(recursing) tmp += ']</li></ul>';
    	return tmp;
    }
    
    function hokey_pokey(){ //that's what it's all about
    	//all processing after loading the xml doc must be referenced here
    	var content='';
    	var output = new Array();
    	xml_Array = xmlToArray(xmlDoc.documentElement);
    	content += arrayToList(xml_Array);
    	document.getElementById("content").innerHTML=content;
    }
    //-->
    </script>
    </head>
    
    <body onload="loadXML('name_address.xml')">
    XML Data:<br>
    <span id="content"></span>
    </body>
    </html>
    This using the following file 'name_address.xml':
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Last update of file Fri, 21 Apr 2006 15:15:36 EDT -->
    <data>
    <time-date><published>Fri, 21 Apr 2006 15:15:36 EDT</published></time-date>
    <records>
    <record><name>TJ</name><address>My Home</address><city>My town</city><occupation>My Girl</occupation><nickname>Depends on the day</nickname><children><son><name>Matt</name><age>15</age><favorite_sport>football</favorite_sport><favorite_sport>baseball</favorite_sport></son><son><name>Austin</name><age>11</age></son><daughter><age>6</age><name>Mallory</name></daughter></children></record>
    
    <record><name>Some Guy</name><address>123 Some Street</address><city>Some City</city><occupation>Farker</occupation><nickname>Some Guy</nickname></record>
    <record><name>Bart</name><address>742 Evergreen Terrace</address><city>Springfield</city><occupation>Student</occupation><nickname>El Barto</nickname></record>
    <record><name>My Car</name><address>My Driveway</address><city>My Town</city><occupation>Car</occupation><nickname>Maverik</nickname></record>
    
    </records>
    </data>
    The root node does not appear in the array as the array is root node.
    Last edited by karlkittler; 04-21-2006 at 09:25 PM.

  • #4
    Master Coder
    Join Date
    Feb 2003
    Location
    UmeŚ, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Darn, I was writing on an answer, you know
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •