Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

getting "undefined" instead of response data

Status
Not open for further replies.

Ghodmode

Programmer
Feb 17, 2004
177
NZ
I'm new with AJAX and I'm having trouble getting the data out of the XML. I'm getting the string "undefined" instead of the values I expect. I'm using the FireBug extension in Firefox to see the XML response and I can verify that all of the data is there. I must just be accessing it incorrectly.

Can someone take a look and suggest what I might be doing wrong?

Here's some of my JavaScript:
Code:
function getResults( type ) {
  var url = "getUserData.php";
  var post_data = "user_id=" + user_id;

  initRequest();

  req.onreadystatechange = processRequest;

  req.open( "POST", url, true );
  req.setRequestHeader( "Content-Type", "application/x-[URL unfurl="true"]www-form-urlencoded"[/URL] );
  req.send( post_data );
} // End getResults function

function processRequest() {
  if ( req.readyState == 4 ) {
    if ( req.status == 200 ) {
      response = req.responseXML.documentElement; // root element

      method = response.childNodes[0].firstChild.data;

      // This idea stolen from
      // [URL unfurl="true"]http://www.xml.com/pub/a/2005/02/09/xml-http-request.html[/URL]
      eval( method + '()' );

      // The problem I'm having only occurs when the method
      // is "updateData"
    }
  }
}

// ...
function updateData() {
  var response_length = response.childNodes.length;
  var data = '<table cellpadding="0" cellspacing="0" border="0">';

  // Start at 1.  0 is the method
  for ( i = 1; i < response_length; i++ ) {
    var field = response.childNodes[i];
    data += "<tr>";
    data += "<td>";
    data += field.tagName;
    data += "</td>";
    data += "<td>";

    // Here's where the problem must be
    data += field.data;

    // And some other methods I've tried ...
    //data += field.text;
    //data += field.firstChild.data;
    //data += field.firstChild.text;
    data += "</td>";
    data += "</tr>";
  }

  data += "</table>";
  dataObj.innerHTML = data;
} // End updateData function

Here's the XML string from the response (formatted for easier reading). I can change the method to "GET" and get the same data by typing the URL in directly ...
Code:
<?xml version="1.0" encoding="UTF-8" ?>
<user_data>
  <method>updateData</method>
  <user_id>Ghodmode</user_id>
  <email>obfu@skated.com</email>
  <fullname>Vincente Aggrippino</fullname>
  <address></address>
  <tel1></tel1>
  <tel2></tel2>
  <website></website>
  <confirmed>0</confirmed>
  <location>localhost</location>
  <http_user_agent>Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060614 Fedora/1.5.0.4-1.2.fc5 Firefox/1.5.0.4 pango-text</http_user_agent>
  <remote_host></remote_host>
  <remote_addr>127.0.0.1</remote_addr>
  <os>Linux</os>
  <browser>Mozilla Firefox</browser>
  <remember_me>1</remember_me>
</user_data>

Thank you,

--
-- Ghodmode

Give a man a fish and he'll come back to buy more... Teach a man to fish and you're out of business.
 
I managed to find a solution. When I accessed a value directly, outside of the loop, I was able to view the value I expected. For example
Code:
alert( response.childNodes[1].firstChild.data );
So, I figured that the JS interpreter was choking when it got to a null value.

Inside my loop, I wrapped the problematic line in a try/catch block...
Code:
try {
  value = response.childNodes[i].firstChild.data;
} catch ( err ) {
  value = "";
}
... and it works.

This feels very much like a hack to me, but it seems to solve the problem.

I welcome comments or suggestions about this approach.

Thank you.

--
-- Ghodmode

Give a man a fish and he'll come back to buy more... Teach a man to fish and you're out of business.
 
>data += field.data;
[tt]data += field.[red]text[/red];[/tt]
 
Cross-browser version would look like this inside the loop.
[tt]
var field = response.childNodes;
switch (field.nodeType) {
case 1 :
data += "<tr>";
data += "<td>";
data += field.tagName;
data += "</td>";
data += "<td>";
data += field.text;
data += "</td>";
data += "</tr>";
break;
case 3 :
break; //do nothing
default :
break; //do nothing
}
[/tt]
 
Tsuji:
Thank you for your attempt, but it doesn't work.

As you can see from my original post, I had already tried field.text. The result is still "undefined". Incidentally, I had also tried field.nodeValue and field.firstChild.nodeValue with the same results.

I also tried the method you suggested in your second post. That also doesn't work. The result is still "undefined".

Since I wasn't familiar with the nodeType property, and you didn't offer an explanation, I looked it up (ref: [URL unfurl="true"]http://www.devguru.com/technologies/xmldom/QuickRef/obj_node.html#types[/url]). While it seems like generally good practice to check the nodeType property when parsing XML, you can see from my XML source that there are no nodes which are not elements (type 1).

--
-- Ghodmode

Give a man a fish and he'll come back to buy more... Teach a man to fish and you're out of business.
 
[1] The point is related to semantically insignificant whitespaces (indents, newlines, ...). Moz engine will pick the noise up as textnodes (nodetype=3) (such as newline following indents etc.)

The .text will work in ie generally for the xml as you have shown. In moz, I think the expansion in my second post demonstrate the device in general. But, I draft it out with reasoning without testing. You probably can refine it to adapt to the case. (One signature you can easy to verify with your set up is to inspect/alert the response.childNodes.length, in ie it would be significantly shorter than in ff. Those surplus in the latter are the noise textnodes which the switch is attempting to ignore---that's the idea.)

[2] As a matter general object model, .data will return undefined and .nodeValue return null for element node type (1). .data and .nodeValue return the same for text node (1). You can see why "method" return correctly whereas in the function, .data fails. In any case, my 2nd post shows the idea that I should construct sample data to test in order to close some loops, maybe; and maybe later.

[3] .text in the function will certainly work throughout if the data are loaded in ie. The childNodes will pick up all the element type (1) with the xml so structured.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top