Jump to content

XML-DOM problems


Mr_CHISOL

Recommended Posts

I have a problem with XML-DOM and Javascript (!).My PHP-file generates a xml-file like this:

<?xml version="1.0" encoding="UTF-8"?><cars> <car>  <id>1</id>  <reg>ABC123</reg>  <make><![CDATA[Volvo]]></make>  <model>V70</model>  <year>-07</year>  <color><![CDATA[rod]]></color>  <ownerid>1</ownerid>  <trans><![CDATA[Automat]]></trans>  <fuel><![CDATA[bensin]]></fuel>  <extra><![CDATA[]]></extra> </car> <car>  <id>2</id>  <reg>CDE345</reg>  <make><![CDATA[Mini]]></make>  <model>Cooper S</model>  <year>-05</year>  <color><![CDATA[rod]]></color>  <ownerid>1</ownerid>  <trans><![CDATA[Automat]]></trans>  <fuel><![CDATA[Flexi-fuel]]></fuel>  <extra><![CDATA[]]></extra> </car></cars>

Than I have this code:

	if (XmlDoc.documentElement.childNodes.length == 1) {		str += showCarInfo( XmlDoc.getElementsByTagName("car")[0] );	} else {		str += '<!--CAR_INFO-->';		showRegList( XmlDoc.documentElement.childNodes, XmlDoc.documentElement.childNodes.length );	}

and then that code call this function (the else-statement):

function showRegList( node, length ){	var str = '<select name="regNos" id="regNos">';	for (i=0; i < length; i++ ) {		/**/str += '<option value="' + i + '">' + node[i].nodeValue + '</option>';/*/		str += '<option value="' + i + '">' + node[i].childNodes[0].nodeValue + '</option>';/**/	}	regsNode = node;	str += '</select>';...]

It's a bit "ruff" as it's in development, but neither of the statements in the loop seem to work, what am I doing wrong and what should I do to make it work??All it displays (if not an error) is just empty or null.Thanks for any help :?)

Link to comment
Share on other sites

you have some weird commenting going on there. Is that the actual script you are running? If not please repost the script you are really using.also you don't seem to be returning anything from that function to displaywhy not something like this

str += showRegList( XmlDoc.documentElement.childNodes, XmlDoc.documentElement.childNodes.length );

function showRegList( node, length ) {	 var str = '<select name="regNos" id="regNos">'; 	 for (i=0; i < length; i++ ) {		 str += '<option value="' + i + '">' + node[i].nodeValue + '</option>';		 str += '<option value="' + i + '">' + node[i].childNodes[0].nodeValue + '</option>';	 }	 regsNode = node; 	 str += '</select>'; 	 return str; ]}

Link to comment
Share on other sites

The commenting is strange I know, but i use it when I have multiple parts of code that I want to test seperately, works like this (bold is commented)/**/str += '<option value="' + i + '">' + node.nodeValue + '</option>';/*/str += '<option value="' + i + '">' + node.childNodes[0].nodeValue + '</option>';/**/or (note the space in the first "block comment")/** /str += '<option value="' + i + '">' + node.nodeValue + '</option>';/*/str += '<option value="' + i + '">' + node.childNodes[0].nodeValue + '</option>';/**/Which let me alternate between two lines (in this case) with just adding/removing a space (I have no keyboard shortcut for comment). Its a bit uglu I know, but it works great during developing.The function I admitted isn't complete. It actaully look like this (I removed it in my first post as it down't matter):

function showRegList( node, length ){	var str = '<select name="regNos" id="regNos">';	for (i=0; i < length; i++ ) {		/**/str += '<option value="' + i + '">' + node[i].nodeValue + '</option>';/*/		str += '<option value="' + i + '">' + node[i].childNodes[0].nodeValue + '</option>';/**/	}	regsNode = node;	str += '</select>';	dialogWContent( 'Kunden med pers.-/org.nummer ' + persNo + ' har flera fordon registrerade i sytemet.' +							'Vänligen välj ett fordon/registreringsnummer i listan nedan, ' +							'för vilken bokningen ska gälla.<br />' +							str, 'Välj registreringsnummer!', function ( ok ) {								if (ok) {									regPos = document.getElementById( 'regNos' ).value;									showCarInfo( regsNode[regPos], true );								}							}, 2, 'okcancel' );}

FYI: The text is in Swedish.dialogWContent() (as dialog()) is my own functions that simply shows a custom dialog using div (I can have 3 on top of each other, each is modal using a semi-ransparent bg that covers everything) (dialog() shows a diaalog with icon or prompt, like "Are you sure?" etc, and dialogWContent() shows a dialog more like a "normal dialog in a app")The function doesn't return cause it's not needed. The function shows a second dialog when the user enters the socialsecurity number of a customer that has more than one car in the first dialog.. (It's all powered with PHP-generated XML and AJAX)None of this inflects on the XML and I still can't get the values from the XML...

Link to comment
Share on other sites

Two questions:How are you getting the XML data into the "XmlDoc" DOM object?Are you specifying in the headers for the response from the PHP page that the content-type is "text/xml"?

Link to comment
Share on other sites

Yes, the content-type is right.The "catching" code:

function getCustCarInfo( id ){	var URL = _DOMAIN_ + _PATH_;	//URL = URL + "khtml_test.php";	URL = URL + "?task=getCustCars&cid=" + id + "&ajax=1";	var first = true;	if (kAjaxDebug == true)		URL = URL + "kdebug=1";	kdebug( 'getCustCarInfo(): URL = ' + URL );	XmlHttp.onreadystatechange = null;	XmlHttp.open( "GET", URL, false );	XmlHttp.send( null );	var XmlDoc = XmlHttp.responseXML;	if (!XmlDoc) {		kdebug( 'getCustCarInfo(): Not xml... <pre>' + XmlHttp.responseText + '</pre>' );		XmlDoc = (new DOMParser()).parseFromString(XmlHttp.responseText, "text/xml");		}	var str = '<h4 class="nside">Fordon</h4><table border="0" class="blank">' /*+				'<tr><td>'*/;	try {		status = XmlDoc.getElementsByTagName("status")[0].childNodes[0].nodeValue;		str += '<tr><td><span class="italic">Hittade inget fordon för kunden</span></td></tr></table>';		dialog( 'Hittade inget fordon för kunden!' +					'Vänligen fyll i fordonets registreringsnummer istället eller' +					' lägg till fordonet i systemet innan du skapar en ny bokning.', 'warning', 'Ange personnummer!', null, null, 2 );		return str;	} catch (e) {}	if (XmlDoc.documentElement.childNodes.length == 1) {		str += showCarInfo( XmlDoc.getElementsByTagName("car")[0] );	} else {		str += '<!--CAR_INFO-->';		showRegList( XmlDoc.documentElement.childNodes, XmlDoc.documentElement.childNodes.length );	}	str += '</table>';	return str;}

the php:

} else if ($task == 'getCustCars') {	$extraXMLInfo = '';	$GLOBALS['stopoutput'] = true;	header( 'content-type: text/xml' );	echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";	echo "<cars>\n";	$w = array();	if (isset($_GET['isPersNo'])) {		if (($_SESSION['level'] < 6) && ($_SESSION['groupName'] != 'admin'))			$w[] = array( 'cid', intval( $_SESSION['cid'] ) );		$w[] = array( 'persNo', $_GET['cid'] );		$kh->getDB()->select( 'customers', 'id', $w );		$w = array();		if ($info = $kh->getDB()->getInfo()) {			$w[] = array( 'owner', intval( $info->id ) );		}	} else		$w[] = array( 'owner', intval( $_GET['cid'] ) );	$kh->getDB()->select( 'cars', '', $w );	$cars = $kh->getDB()->getData( true );	if (!empty( $cars )) {		foreach ($cars as $car) {			echo " <car>\n";			echo "  <id>" . $car->id . "</id>\n";			echo "  <reg>" . $car->reg . "</reg>\n";			echo "  <make><![CDATA[" . $car->maker . "]]></make>\n";			echo "  <model>" . $car->model . "</model>\n";			echo "  <year>" . $car->year . "</year>\n";			echo "  <color><![CDATA[" . $car->color . "]]></color>\n";			echo "  <ownerid>" . $car->owner . "</ownerid>\n";			echo "  <trans><![CDATA[" . $car->trans . "]]></trans>\n";			echo "  <fuel><![CDATA[" . $car->fuel . "]]></fuel>\n";			echo "  <extra><![CDATA[" . $car->extra . "]]></extra>\n";			echo " </car>\n";		}	} else		echo " <status>-404</status>\n";	echo "</cars>\n\n";	exit();

Link to comment
Share on other sites

OK, I can see two possible issues. The first is the building of the select and options elements by using a string. The only reliable success I've ever had with dynamically building dropdown menus is by using the XML DOM:

var select = document.createElement("select");for(var i = 0; i < 10; i++){	var option = document.createElement("option");	option.value = i;	option.appendChild(document.createTextNode(i));	select.appendChild(option);}

The second issue is that, depending on the browser that you're using, there may be more nodes in your XML document that you might expect.

<car><id>1</id><reg>ABC123</reg><make><![CDATA[Volvo]]></make></car>
can be represented differently by the DOM than
<car><id>1</id><reg>ABC123</reg><make><![CDATA[Volvo]]></make></car>
You may need to add a check in your loop to verify that the nodeType is an element rather than a text node. See this URL for a reference: http://www.w3schools.com/dom/dom_nodetype.asp
for (i=0; i < length; i++ ){	if(node[i].nodeType == 1)	{		// we have an element node.	}	else	{		// it's some other type of node, let's skip it.		continue;	}}

Link to comment
Share on other sites

First, the else-statement and continue is unnecessary (unless you trying to be extremely "clear") as it's nothing after the if anyway.Second, I can't (don't need and don't want to) use DOM to create the select-element, as I need it as an string to be inserted in the content of the dialog. The dialog takes it content as a string with (X)HTML and not DOM, there's three (good?) reasons for that: 1. It's easier to use a string 2. as most of the dialogs content is generated by PHP (and then sent to the browser using XML etc) It would be a pain to use DOM 3. I don't need to, it works great without it :?)Then, the main problem was that I had forgotten something (something that you apparently missed too): get the value from the reg-element. The loops goes thru the cars, but then to be able to show the registrationnumbers I needed to get it from the reg-element for each car (and not directly from the car node/element). On the other hand it still hadn't worked correctly if you didn't point out the problem with node types...So thanks for your help! :?)Here's the code I'm using now.

function showRegList( node, persNo ){	var select = '<select name="regNos" id="regNos" style="width: 9em">';	regsNode = new Array();	for (var i=0; i < node.length; i++ ) {		if (node[i].nodeType == 1) {			select += '<option value="' + i + '">' + node[i].getElementsByTagName( 'reg' )[0].firstChild.nodeValue + '</option>';			regsNode.push( node[i] );		}	}	select += '</select>';	dialogWContent( 'Kunden med pers.-/org.nummer ' + persNo + ' har flera fordon registrerade i sytemet.' +							'Vänligen välj ett fordon/registreringsnummer i listan nedan, ' +							'för vilken bokningen ska gälla.'							'<div style="text-align:center">' + select + '</div>', /** The select box **/							'Välj registreringsnummer!', function ( ok ) {								if (ok) {									regPos = document.getElementById( 'regNos' ).value;									showCarInfo( regsNode[regPos], true );								}							}, 2, 'okcancel' );}

and the calling script:

	if (XmlDoc.documentElement.childNodes.length == 1) {		str += showCarInfo( XmlDoc.getElementsByTagName("car")[0] );	} else {		str += '<!--CAR_INFO-->';		showRegList( XmlDoc.documentElement.childNodes );	}

Oh, one quick question (doesn't matter really as this works): Why can't I use XmlDoc.getElementsByTagName("car") to call showRegList() with??

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...