views:

252

answers:

1

I can't figure out how to access the data between the inner nested tags. When I run this javascript, all I see is "Null".

Here is what my xml file named "bboard.xml" looks like:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Designed by Someone -->
<bulletinboard>
<article>
<title lang="en"><h2>eeeeeeeeegg #1</h2></title>
<detail><span class="detail">aaaaapple</span>&lt;a href="../data/csr.html#artcl1"> ...more &lt;/a></detail>
<date>12/09/09</date>
</article>
</bulletinboard>

Here is the javascript named "loadxmldoc.js":

function loadXMLDoc(dname) 
{
try //Internet Explorer
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    xmlDoc=document.implementation.createDocument("","",null);
    }
  catch(e) {alert(e.message)}
  }
try 
  {
  xmlDoc.async=false;
  xmlDoc.load(dname);
  return(xmlDoc);
  }
catch(e) {alert(e.message)}
return(null);
}

And finally, here is the actual HTML page where I want to display the result of javascript. It is called "javdemo.html":

<html>
<head>
<script type="text/javascript" src="loadxmldoc.js"> 
</script>
</head>

<body>


<div>
<script type="text/javascript">
xmlDoc=loadXMLDoc("bboard.xml");

var x=xmlDoc.getElementsByTagName("title");
var y=xmlDoc.getElementsByTagName("detail");
var z=xmlDoc.getElementsByTagName("date");

document.write("<h4>"+"A Live Bulletin Board"+"</h4>");
       for (i=0;i<x.length;i++)
  { 

  document.write("<h1>"+x[i].childNodes[0].nodeValue+"</h1>"); 
  document.write(y[i].childNodes[0].nodeValue);
  document.write(z[i].childNodes[0].nodeValue);
  document.write("<p>"+"&nbsp;"+"</p>");
  // document.write("</div>")
  }
</script>
</div>
</body>
</html>

This probably won't show the full code in your browser. By the way how do you escape html tags here on stack overflow?

A: 
z[i].childNodes[0].nodeValue

...is OK. The firstChild of z[0] is a Text node, whose nodeValue (or data) is '12/09/09'.

x[i].childNodes[0].nodeValue

...isn't so good. x[0] is an Element node with tagName equal to 'h2'. Elements don't have any nodeValue, hence the null.

You could say x[i].firstChild.firstChild.data to get the data from the Text node inside the <h2> element, assuming there's always exactly one.

Using document.write to output the strings you are getting is also problematic. If there's stuff like &lt;script> in the text content and you write that to HTML without escaping, you've got a cross-site-scripting vulnerability.

If what you actually need to do is extract the element content from the XML document, that's not so easy. There's no standard way to re-serialise node content from a plain XML Element like there is the HTML DOM with HTMLElement.innerHTML.

What you can do is recurse into the children re-creating the XML Element and Text nodes as HTML ones. The document.importNode method should be able to do this, except it doesn't work in IE, so you'd have to do it yourself:

<div id="board"></div>
<script type="text/javascript">
    var xdoc= loadXMLDoc('board.xml');
    var titles= xmlDoc.getElementsByTagName('title');
    var details= xmlDoc.getElementsByTagName('detail');
    var dates= xmlDoc.getElementsByTagName('date');

    var board= document.getElementById('board');
    for (var i= 0; i<titles.length; i++) {
        appendImportedInner(board, titles[i]);
        appendImportedInner(board, details[i]);
        board.appendChild(appendImportedInner(document.createElement('p'), dates[i]));
    }

    // Import Text and Element nodes inside a parent XML node to a target HTML node
    // Currently ignores any other type of node, such as comments
    //
    function appendImportedInner(dest, parent) {
        for (var i= 0; i<parent.childNodes.length; i++) {
            var child= parent.childNodes[i];
            if (child.nodeType==3) {  // TEXT_NODE
                dest.appendChild(document.createTextNode(child.data));
            }
            if (child.nodeType==1) {  // ELEMENT_NODE
                dest.appendChild(document.createElement(child.tagName));
                for (var ai= 0; ai<child.attributes.length; ai++) {
                    var attr= child.attributes[ai];
                    dest.lastChild.setAttribute(attr.name, attr.value);
                }
                appendImportedInner(dest.lastChild, child);
            }
        }
        return dest;
    }
</script>

doing it with DOM methods allows you to forget nasty document.write and set the content at any time later in the load process, which also means you could make that XML document loading asynchronous with a callback to fill in the board, instead of the browser-pausing synchronous loader you've got at the moment.

In any case, Document.load as used in your current loadXMLDoc() is not a standard XML DOM method and won't work on WebKit (Chrome, Safari, ...). To load an XML file from the server you are better off using a normal XMLHttpRequest to fetch it: is simpler and much more widely compatible.

bobince
I tried your code and I am getting a completely blank page now in IE. Same thing in firefox too. Basically I wanted to show hyperlink link from xml and I can't think of any other way to do it, as you say serialise it from xml.
megatr0n
Works for me (just the above code block, after the `loadxmldoc` include).
bobince
Thanks. It works now. Just corrected "board.xml" to "bboard.xml".
megatr0n