www.webdeveloper.com
Results 1 to 5 of 5

Thread: Null DOM/XML elements? Help!

  1. #1
    Join Date
    Oct 2008
    Posts
    7

    Null DOM/XML elements? Help!

    Hi all,

    Thought I would register here to ask a question as it seems this is an active forum.

    I am trying to extract some info from an XML file. Here is a snippet of it:

    Code:
    <TVLISTINGSRESULTS>
    	<CHANNELS>
    		<CHANNEL>
    			<NAME>ABC</NAME>
    			<SHOW>
    				<TIMESLOT>11:00pm -  1:05am</TIMESLOT>
    				<LINK>N/A</LINK>
    				<SHOWNAME>Local Programming</SHOWNAME>
    			</SHOW>
    			<SHOW>
    				<TIMESLOT> 1:05am -  5:00am</TIMESLOT>
    				<LINK>N/A</LINK>
    				<SHOWNAME>Local Programming</SHOWNAME>
    			</SHOW>
    		</CHANNEL>
    		<CHANNEL>
    			<NAME>CBS</NAME>
    			<SHOW>
    				<TIMESLOT>12:00am -  6:00am</TIMESLOT>
    				<LINK>N/A</LINK>
    				<SHOWNAME>Local Programming</SHOWNAME>
    			</SHOW>
    		</CHANNEL>
    		<CHANNEL>
    			<NAME>FOX</NAME>
    			<SHOW>
    				<TIMESLOT>12:00am -  6:00am</TIMESLOT>
    				<LINK>N/A</LINK>
    				<SHOWNAME>Local Programming</SHOWNAME>
    			</SHOW>
    		</CHANNEL>
    	</CHANNELS>
    </TVLISTINGSRESULTS>
    Easy enough, right? And, I am using the following code to try to grab some info. I am working in the second function "buildMenus()".

    Code:
    <html>
    <head>
    <title>Search Listings</title>
    
    <script language="javascript">
    <!--
    
    function beginProgram()
    {
      var URL;
      URL="file2.xml";  //which has the contents above from the XML snippet
    
      if (window.ActiveXObject) //Checking if the browser is IE
      {
      //code removed to save space...
      }
      else if (document.implementation && document.implementation.createDocument)//for mozilla based browsers
      {
        var xmlDoc= document.implementation.createDocument("","doc",null); // NS
        xmlDoc.async=false; //make sure doc is fully loaded
        loaded = xmlDoc.load(URL);
        if(!loaded)
        {
          alert("Error in XML file");
        }
        else
        {
          buildMenus(xmlDoc);
        }
      }
    }
    
    function buildMenus(XMLstuff) {
    
      var tree = XMLstuff.documentElement;  //documentElement = "TVLISTINGSRESULTS
      var treenodes=tree.childNodes;
    
    //alert(tree.childNodes[1].nodeName); = CHANNELS
    //alert(tree.childNodes[1].childNodes[1].nodeName); = CHANNEL
    
      alert(tree.childNodes[1].childNodes[5].childNodes[1].nodeValue);
    
    //I can get the <CHANNEL>, <NAME>, <TIMESLOT> to show up
    //but I cannot get alert() to show the contents between these tags!!
    //which would be "ABC" for channel, "Local Programming" for name, or the time for the <TIMESLOT>.
      
    
    document.write(tree.childNodes[1].childNodes[3].childNodes[5].childNodes.length);
      for(i=0; i<tree.childNodes[1].childNodes[3].childNodes[5].childNodes.length;i++){
        document.write(tree.childNodes[1].childNodes[3].childNodes[5].childNodes[i].nodeValue);
      }
    }
    
    -->
    </script>
    
    </head>
    <body onLoad="beginProgram()">
    
    </body>
    </html>
    My issue is this: I am able to find the XML tag names, such as <NAME> or <SHOW> or <TIMESLOT>, etc, with .nodeName, but changing to .nodeValue I am unable to get that information to show up. For example, x.x.x.nodeName = "NAME", but x.x.x.nodeValue = null, or is empty, not the "ABC" or "CBS" which I am expecting.

    I have made some simple alert statements to simply show that I am able to find them, but all I get back is "null" or "" (nothing).

    Any idea what I am doing wrong?

    Thanks!

  2. #2
    Join Date
    Mar 2007
    Location
    Athens, Greece
    Posts
    177
    Hi and welcome!

    My issue is this: I am able to find the XML tag names, such as <NAME> or <SHOW> or <TIMESLOT>, etc, with .nodeName, but changing to .nodeValue I am unable to get that information to show up. For example, x.x.x.nodeName = "NAME", but x.x.x.nodeValue = null, or is empty, not the "ABC" or "CBS"
    1) The element itself has not a nodeValue.. Is the child textNode that you can get its value..
    Example in the element: <NAME>ABC</NAME>
    To get the "ABC" value must get the NAME's firstChild nodeValue.. (the text node's "ABC" value, which is child of the <NAME> element)

    2) Also since IE and rest browsers translate differently the white-spaces (new lines, tabs, spaces, etc) is not safe to use eg. aNode.childNodes[1] or aNode.firstChild, since the non IE browsers consider the new lines, spaces etc on the xml, as part of the document tree.. Thus can get errors of null values or different lengts of children etc..

    Is better to use the command: aNode.getElementsByTagName("Node_Name")

    Example like this (to get the NAME's value):
    Code:
    alert( tree.getElementsByTagName("NAME")[0].firstChild.nodeValue  ) //ABC
    Notes:
    a) The "getElementsByTagName()" returns a node list (say array) of all given elements name, so need to specify an array index to get the appropriate element.
    Example (see the array index)
    Code:
    tree.getElementsByTagName("NAME")[0]  // gets the first <NAME> element
    b) As already stated to get an elements value actually means to get its 1st child text node value. (The value "ABC" is a separate node -textNode- child of the <NAME> element)


    Kostas
    Last edited by Kostas Zotos; 10-20-2008 at 03:17 PM.

  3. #3
    Join Date
    Oct 2008
    Posts
    7
    Hi Kostas, thank you for your reply. This was very helpful.

    By using firstChild.nodeValue, I have been able to complete my entire program in FireFox. Unfortunately, I am having trouble in IE.

    I get all the way to a section of my code that has a for loop like this:
    Code:
    alert("before loop");
    
    for(i=1; i<tree.childNodes[1].childNodes.length;){
      alert("entered loop");
      menu1text+="<option value="+i+">"+tree.childNodes[1].childNodes[i].childNodes[1].firstChild.nodeValue+"</option>";
      i = i+2;
    }
    When I run the code, I get the alert message "before loop". Unfortunately, I do not get the "entered loop" message. Does IE not like to look at childNodes.length? Firefox is OK with this.

    Also, will the "tree.childNodes[1].childNodes[i].childNodes[1].firstChild.nodeValue" be OK?

    Thank you very much!

  4. #4
    Join Date
    Mar 2007
    Location
    Athens, Greece
    Posts
    177
    Hi,

    Don't mention it!

    When I run the code, I get the alert message "before loop". Unfortunately, I do not get the "entered loop" message. Does IE not like to look at childNodes.length? Firefox is OK with this.

    The problem in this case is the different way the IE and non-IE browsers interpret the white-spaces that exist inside your XML file.

    Example, if you press the Enter to change line, or insert a space before an element in your original xml file, this space or enter (LineFeed character) considered as a textNode by the non-IE browsers and this change the total number of children nodes.. [NS, FireFox, etc return more childNodes than they really exist -because they counts also the white-spaces]

    Run this example to see the different number of children in IE and rest browsers:

    Code:
    // The number of children is different in IE and non-IE browsers:
    
    var Output=""
    
    for (var i=0;i<tree.childNodes.length;i++){
       Output+="Index: " + i + ",    nodeName:  "+tree.childNodes[i].nodeName + ",   nodeType:  " + tree.childNodes[i].nodeType + "\n"
    }
    
    alert("tree number of Children:  " +tree.childNodes.length+"\n-------------------\n"+Output+"\n------------------ \n\n nodeType: \n\n 1 => Element Node \n 2 => Attribute Node \n 3 => Text Node");
    -----------------------------

    Also, will the "tree.childNodes[1].childNodes[i].childNodes[1].firstChild.nodeValue" be OK?
    No. Due to the reason of the different translation of white-spaces in your XML file (from IE versus the rest browsers), the: childNodes[1], childNodes[i] and even the "firstChild" are unsafe (the same command may represent different nodes of the XML file or even not existing nodes in the 2 browser types -IE and rest browsers- )

    An alternative (safer) method [based on "getElementsByTagName()" command] :

    // Safe way to get element values, eg. the NAMES values:

    var Names=tree.getElementsByTagName("NAME") // Returns a node list (array) with all the <NAME> elements in the xml document
    var menu1text=""

    for(var i=0; i<Names.length;i++){
    menu1text+="<option value='" + (i+1) + "'>" + Names[i].firstChild.nodeValue + "</option>\n";
    }

    alert(menu1text);


    //document.writeln("<select size='1'>\n"+menu1text+"</select>")

    document.getElementById("Sel").innerHTML="<select size='1'>"+menu1text+"</select>" // Need an empty <div id="Sel"></div> placeholder for the "select" to exist inside your HTML body.

    Or a more comlex approach is to run a "for" loop for all the children of a given node and check the nodeType* (and possibly the nodeName) of each child in order to be sure that you act on an element rather than a textNode (eg. you may try to get the children of a textNode which has no meaning. Remember also that white-spaces (newLines , spaces) shown as textNodes from non-IE browsers.

    *The Element nodeType is 1 while textNodes' Type is 3.

    Cheers!

    Kostas
    Last edited by Kostas Zotos; 10-21-2008 at 10:03 AM.

  5. #5
    Join Date
    Oct 2008
    Posts
    7
    Hi Kostas, I think I forgot to mention this before, but thank you very much for your help! I got everything working. Now.. onto my next problem over in the java servlet area!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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



Recent Articles