Click to See Complete Forum and Search --> : Presenting XML data in HTML problem


Hilton
03-20-2006, 12:54 PM
Hello, there! I have the following problem. I am trying to present data that resides in a XML file in a HTML page. I got a code sample from someone over the Internet and modified to my needs, but there is a snag. It does a great job presenting the data, as long as all fields in the XML database have a value, but if one field is empty, it fails.

In this database, some of the fields sometimes are empty, such as "Middle Initial," for example. I cannot control it, as the data will be populated by users. One single empty field makes the code fail. In the example below, if for instance the cause of death is blank, the code fails to present the data.

I think my question is how to adjust the JavaScript code to skip or add a blank character when it finds an empty field while reading the XML database.

Thanks in advance for your help! :confused:

Here is the sample HTML code:

<html>
<head>
<title>Page title</title>
<SCRIPT type="text/javascript" src="importxml.js">
// Load import XML file
</SCRIPT>

</head>

<body>

<SCRIPT type="text/javascript">

//Specify path to xml file
///var xmlsource="../xml/directory.xml"

//Specify record name of xml file
///var xmlrecord="extension"

var t = importXML()

</SCRIPT>


Roman Emperors<br>


<p id="writeroot">


</body>
</html>

Here is the JavaScript code:

// Thanks to Peter-Paul Koch, from QuirksMode.org

// Specify path to xml file
var xmlsource="emperors.xml"

// Specify path to xml file
var xmlsubtag="extension"

//Regular expression used to match any non-whitespace character
var notWhitespace = /\S/

function importXML()
{
if (document.implementation && document.implementation.createDocument)
{
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.onload = createTable;
}
else if (window.ActiveXObject)
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.onreadystatechange = function () {
if (xmlDoc.readyState == 4) createTable()
};
}
else
{
alert('Your browser can\'t handle this script');
return;
}
/// xmlDoc.load('emperors.xml');

xmlDoc.load(xmlsource);
}

function createTable()
{
/// var x = xmlDoc.getElementsByTagName('emperor');
var x = xmlDoc.getElementsByTagName(xmlsubtag);

/// //REMOVE white spaces in XML file. Intended mainly for NS6/Mozilla
/// for (i=0;i<x[0].childNodes.length;i++){
/// if ((x[0].childNodes[i].nodeType == 3)&&(!notWhitespace.test(x[0].childNodes[i].nodeValue))) {
/// x[0].removeChild(x[0].childNodes[i])
/// i--
/// }
/// }


var newEl = document.createElement('TABLE');
newEl.setAttribute('cellPadding',5);
var tmp = document.createElement('TBODY');
newEl.appendChild(tmp);
var row = document.createElement('TR');
for (j=0;j<x[0].childNodes.length;j++)
{
if (x[0].childNodes[j].nodeType != 1) continue;
var container = document.createElement('TH');
var theData = document.createTextNode(x[0].childNodes[j].nodeName);
container.appendChild(theData);
row.appendChild(container);
}
tmp.appendChild(row);
for (i=0;i<x.length;i++)
{
var row = document.createElement('TR');
for (j=0;j<x[i].childNodes.length;j++)
{
if (x[i].childNodes[j].nodeType != 1) continue;
var container = document.createElement('TD');

///Test if the record field is empty
var test = x[i].childNodes[j].nodeType;
var test0 = x[i].childNodes[j].firstChild.length;
var test1 = x[i].childNodes[j].firstChild.nodeValue;
if (x[i].childNodes[j].lenght != 0)
var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);
else
var theData = document.createTextNode('');

container.appendChild(theData);
row.appendChild(container);
}
tmp.appendChild(row);
}
document.getElementById('writeroot').appendChild(newEl);
}

And here is the sample XML database:

<emperors>
<emperor>
<name>Augustus</name>
<rule>27BC-14AD</rule>
<death>Peaceful</death>
</emperor>
<emperor>
<name>Tiberius</name>
<rule>14-37</rule>
<death>Murdered by his great-nephew and the commander of his bodyguard</death>
</emperor>
<emperor>
<name>Caligula</name>
<rule>37-41</rule>
<death>Murdered by the commander of his bodyguard (a different one than the one before)</death>
</emperor>
<emperor>
<name>Claudius</name>
<rule>41-54</rule>
<death>Poisoned by his fourth wife</death>
</emperor>
<emperor>
<name>Nero</name>
<rule>54-68</rule>
<death>Suicide after losing the Empire</death>
</emperor>
</emperors>

Khalid Ali
03-21-2006, 10:59 PM
don't see an extension tag in the xml file. And second could you post a link to the page where you have this implemented and point out the cells where u think its showing the problem?

Hilton
03-24-2006, 03:11 PM
Hello, there! Sorry about it. I have so many versions that I got confused myself.

But ere is the link to the original code I am working with.

http://www.quirksmode.org/dom/importxml.html

The code itself works fine, but with one caveat: All fields in the xml file have to have a value. In the example presented, the file emperors.xml has data on every single field, as you can see below.

I am trying to use a slightly modified version of this code for a directory page (phone extensions, names, etc.)

In any event, even on the example code and xml file, if you empty out one of the fields, such as death for one of the emperors, the script fails and nothing is presented. What I wanted it to do was to present an empty cell in its place.

For example, let's assume that the record for emperor Augustus was as such:
- <emperor>
<name>Augustus</name>
<rule>27BC-14AD</rule>
<death></death>
</emperor>

Notice the <death></death> field. If make this modification on the xml file, the script fails and nothing is produced. I have a hunch that the problem is with the "importXML" function and not the "createTable" function, but I am at a loss right now.

Thanks in advance for all the help.




emperors.xml file:

- <emperors>
- <emperor>
<name>Augustus</name>
<rule>27BC-14AD</rule>
<death>Peaceful</death>
</emperor>
- <emperor>
<name>Tiberius</name>
<rule>14-37</rule>
<death>Murdered by his great-nephew and the commander of his bodyguard</death>
</emperor>
- <emperor>
<name>Caligula</name>
<rule>37-41</rule>
<death>Murdered by the commander of his bodyguard (a different one than the one before)</death>
</emperor>
- <emperor>
<name>Claudius</name>
<rule>41-54</rule>
<death>Poisoned by his fourth wife</death>
</emperor>
- <emperor>
<name>Nero</name>
<rule>54-68</rule>
<death>Suicide after losing the Empire</death>
</emperor>
</emperors>

NogDog
03-24-2006, 03:30 PM
How about changing this...

if (x[i].childNodes[j].lenght != 0)

...to this...

if (x[i].childNodes[j].length != 0)

Hilton
03-29-2006, 10:37 AM
Thanks for the suggestions, but it still does not work. I put together a working version of the test script that I think might be easier to visualize the problem. Please find the working versions of the XML data file and the HTML and JavaScript code towards the end of this message.

The problem is when one of the fields (children) of the XML file is empty, as in the following example, if the "rule" field is empty, the script fails and does not present anything.

<emperor>
<name>Claudius</name>
<rule></rule>
<death>Poisoned by his fourth wife</death>
</emperor>


I tried so far the following commands to test if the next field is empty, but they all fail at this point is the field is indeed empty.

var test = x[i].childNodes[j].nodeType;
var test1 = x[i].childNodes[j].firstChild.nodeValue;
var test0 = x[i].childNodes[j].firstChild.length;

What I am looking for is a command or way for the script to recognize that the next field is empty WITHOUT crashing, and allowing me to do something like this:

if (field is empty)
theData = "";

and move along, creating the table with the empty cell.

Again, I thank you all in advance for all the help.

Regards. :confused:

Here is the working XML data file (there are no empty fields!):

<?xml version="1.0" encoding="utf-8" ?>
<emperors>
<emperor>
<name>Augustus</name>
<rule>27BC-14AD</rule>
<death>Peaceful</death>
</emperor>
<emperor>
<name>Tiberius</name>
<rule>14-37</rule>
<death>Murdered by his great-nephew and the commander of his bodyguard</death>
</emperor>
<emperor>
<name>Caligula</name>
<rule>37-41</rule>
<death>Murdered by the commander of his bodyguard (a different one than the one before)</death>
</emperor>
<emperor>
<name>Claudius</name>
<rule>41-54</rule>
<death>Poisoned by his fourth wife</death>
</emperor>
<emperor>
<name>Nero</name>
<rule>54-68</rule>
<death>Suicide after losing the Empire</death>
</emperor>
</emperors>


Here is the working code in HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
<TITLE>JavaScript - Import XML Document</TITLE>

<SCRIPT type="text/javascript">
// Load import XML file

function importXML(xmlsource, xmlrecord)
{
if (document.implementation && document.implementation.createDocument)
{
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.onload = createTable;
}
else if (window.ActiveXObject)
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.onreadystatechange = function () {
if (xmlDoc.readyState == 4) createTable()
};
}
else
{
alert('Your browser can\'t handle this script');
return;
}
xmlDoc.load(xmlsource);
}

function createTable()
{
var x = xmlDoc.getElementsByTagName(xmlrecord);
var newEl = document.createElement('TABLE');
newEl.setAttribute('cellPadding',5);
var tmp = document.createElement('TBODY');
newEl.appendChild(tmp);
var row = document.createElement('TR');
for (j=0;j<x[0].childNodes.length;j++)
{
if (x[0].childNodes[j].nodeType != 1) continue;
var container = document.createElement('TH');
var theData = document.createTextNode(x[0].childNodes[j].nodeName);
container.appendChild(theData);
row.appendChild(container);
}
tmp.appendChild(row);
for (i=0;i<x.length;i++)
{
var row = document.createElement('TR');
for (j=0;j<x[i].childNodes.length;j++)
{
if (x[i].childNodes[j].nodeType != 1) continue;
var container = document.createElement('TD');

// Here is where I am trying to find out with these variables if the next field (child) is empty, but so far with no sucess...
///Test if the record field is empty
//var y = 1,
var test = x[i].childNodes[j].nodeType;
// var test1 = x[i].childNodes[j].firstChild.nodeValue;
// var test0 = x[i].childNodes[j].firstChild.length;
if (x[i].childNodes[j].length != 0)
var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);
else
var theData = document.createTextNode('');

var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);



container.appendChild(theData);
row.appendChild(container);
}
tmp.appendChild(row);
}
document.getElementById('writeroot').appendChild(newEl);
}

</SCRIPT>

</head>

<body >

Roman Emperors<br>

<p id="writeroot"></p>

<SCRIPT type="text/javascript">

//Specify path to xml file
var xmlsource="emperors.xml"

//Specify record name of xml file
var xmlrecord="emperor"

var t = importXML(xmlsource, xmlrecord)

</SCRIPT>

</body>
</html>

Ultimater
07-18-2006, 08:43 PM
I have been messing with the same script but is doesn't work in Opera -- only IE and Firefox.
http://www.aplustv.com/public_stuff/ajax/importing_an_xml_document.htm
Is there something wrong with the XML?
http://www.aplustv.com/public_stuff/ajax/emperors.xml
None of the fields are empty.
Opera understood document.implementation as well as document.implementation.createDocument when I tested them with an alert however my page fails to load. The XML file must be messed up an I don't know what it can be.

Opera's error:

Importing external XML data
http://www.aplustv.com/public_stuff/ajax/importing_an_xml_document.htm
Javascript URL thread: "javascript:importXML()"
Error:
name: TypeError
message: Statement on line 21: Type mismatch (usually a non-object value used where an object is required)
Backtrace:
Line 21 of inline#1 script in http://www.aplustv.com/public_stuff/ajax/importing_an_xml_document.htm
xmlDoc.load("emperors.xml");
Line 1 of unknown script
importXML();

Seems to me the statement xmlDoc.load("emperors.xml") within the importXML function is failing because the XML file is corrupted.

Ultimater
08-04-2006, 10:16 PM
I found out how to serve Oprea with DOM level3's document.implementation.createLSParser.
Behold, my cross-browser XMLDOM parser:
http://www.aplustv.com/public/xmldom.htm
Tested in IE6.0, Opera8 and Firefox1.0.7