Helpful Information
 
 
Category: XML
Importing External XML Files

I was wondering if there was a way to import data from an external XML file into an HTML file, and manipulate that data on the HTML page.

I know it can be done when the XML data is inside the HTML page... but as far as manipulating it, I've only learned how to do that with IE, but not Gecko.

var doc = document.implementation.createDocument('', null, null);
doc.load('somedoc.xml');

doc.onload = function() {
alert(doc.documentElement.nodeName);
}

That is how you load an XML document dynamically in Gecko.
You manipulate it with DOM1, DOM2, and DOM3 features.

IE supports an <xml id="fruits" src="data.xml" /> element for HTML. Of course, it's not standard markup.

From there, you would go:

var xml_doc = fruits.XMLDocument

(I think. I covered it in Chapter 36 of my book.)

And for the record, DOM 3 hasn't been finalized yet, so the methods Jason notes are not cast in stone for future browsers.

Originally posted by Alex Vincent
And for the record, DOM 3 hasn't been finalized yet, so the methods Jason notes are not cast in stone for future browsers.

The XMLExtras project at Mozilla doesn't describe XMLDocument.prototype.load as a DOM3 Load and Save method, although it is, which leads me to believe at least in Mozilla it will hang around for a while.

var xml_doc = new ActiveXObject("Microsoft.XMLDOM")
xml_doc.async = false
xml_doc.load("filename.xml")

the IE equivalent to Jason's Gecko method.

patrick

Okay...

I set up a script to sniff out IE and Gecko, and had everything load based on that. JKD, the alert box read "parsererror". The IE script that mpjbrennan wrote didn't have any sort of alert, so I'm not sure if it worked right or not.

Here's the XML file I've got saved as "cust.xml":



<XML ID="CUSTOMERS" VERSION="1.0"?>

<RESTAURANT>
<NAME>A Special Place</NAME>
<ADDRESS>3124 Williamsburg Dr.</ADDRESS>
</RESTAURANT>

<RESTAURANT>
<NAME>Al Fresco Cafe</NAME>
<ADDRESS>3398 El Camino Real</ADDRESS>
</RESTAURANT>

</XML>


I'm not sure if the opening XML tag is right or not.

Here is the HTML file I've written named "importXML.htm".



<html>
<head>
<title>Importing and Manipulating XML</title>
<script language="javascript" src="sniffer.js"></script>
<script language="javascript">
<!--
if (browser.gecko)
{
var doc = document.implementation.createDocument('', null, null);
doc.load('cust.xml');
}

else if (browser.ie)
{
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = false;
doc.load('cust.xml');
}
//-->
</script>
</head>
<body>
<script language="javascript">
<!--

//-->
</script>
</body>
</html>


Assuming that this has caused the XML document to be "imported"... where do I go from here? How do I access my XML data?

you could do the following:

node_list = xml_doc.getElementsByTagName("RESTAURANT")


and then extract the data you want as child nodes of the elements making up the RESTURANTS array.


patrick

I'm actually not all that familiar with the DOM. Child Nodes? How exactly does that work?

node_list = xml_doc.getElementsByTagName("RESTAURANT")

Does this return an array of RESTAURANT? As in RESTAURANT[0], RESTAURANT[1], RESTAURANT[2], etc.

Could I use something like xml_doc.getElementsByTagName("RESTAURANT")[0].getElementsByTagName("NAME")

Have a look at the following:

http://www.patrick-brennan.com/xml/XfaMiLy_historian.html

patrick

Okay...

I looked at your site, and got a bunch of code from it. I've cleaned it up to simplify it as much as possible, not only so that I can read it, but I like code to be generic.

Anyways, the "cust.xml" file that I refer to is the same that I've posted earlier in this thread.

This is the new importXML.htm file I've got...



<html>
<head>
<title>Importing and Manipulating XML</title>
<script language="javascript">
<!--
/*************************************
DECLARE GLOBAL VARIABLES
*************************************/
var c='';
var d='';
var e='';
var f='';
var g='';


/*************************************
MOZILLA - EXTRACT NODE INFORMATION
*************************************/
function readFileMoz()
{
node_list = xml_doc.getElementsByTagName("RESTAURANT")

for (i = 0; i <= node_list.length-1; i++)
{
c = node_list[i].childNodes[1].nodeValue
d = node_list[i].childNodes[3].nodeValue
e = node_list[i].childNodes[5].nodeValue
f = node_list[i].childNodes[7].nodeValue
g = node_list[i].childNodes[9].nodeValue

}
}


/*************************************
INTERNET EXPLORER - EXTRACT NODE INFORMATION
*************************************/
function readFileIE()
{
node_list = xml_doc.getElementsByTagName("RESTAURANT")

for (i = 0; i <= node_list.length-1; i++)
{
c = node_list[i].childNodes[0].nodeValue
d = node_list[i].childNodes[1].nodeValue
e = node_list[i].childNodes[2].nodeValue
f = node_list[i].childNodes[3].nodeValue
g = node_list[i].childNodes[4].nodeValue
}
}


/*************************************
This function loads the file.
*************************************/
function importXML(zFileName)
{
var moz = (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined');
var ie = (typeof window.ActiveXObject != 'undefined')

if (moz)
{
xml_doc = document.implementation.createDocument("", "", null)
xml_doc.onload = readFileMoz
}

else if (ie)
{
xml_doc = new ActiveXObject("Microsoft.XMLDOM")
xml_doc.onreadystatechange = function()
{
if (xml_doc.readyState == 4) setTimeout(readFileIE,0)
}
}

xml_doc.load(zFileName)
}

importXML('cust.xml');


//-->
</script>
</head>
<body>
<script language="javascript">
<!--
document.write('C='+c+'<br>');
document.write('D='+d+'<br>');
document.write('E='+e+'<br>');
document.write('F='+f+'<br>');
document.write('G='+g+'<br>');
//-->
</script>
</body>
</html>


I used the document.write() just so I could see what all was coming up, but to no avail. Did I miss something when I stripped out superfluous code? I can't seem to figure out what the problem is.

You have a couple of problems:

1. Your xml file is invalid - the xml declaration must be in lower case, and you must enclose all the elements in a root element.

2. The node numbering used in the script is incorrect. The text value of a node is contained in a text node attached to it - so you need to go down one more level to extract it.

3. You didn't declare xml_load as a global variable so it was local to the function importXML()

I am attaching a revised cust.xml and an html page which will display the information you want in alert boxes. I've checked it with IE6 and Mozilla 1.0.

patrick

----------------------------------

<?xml version="1.0"?>

<LIST>

<RESTAURANT>
<NAME>A Special Place</NAME>
<ADDRESS>3124 Williamsburg Dr.</ADDRESS>
</RESTAURANT>

<RESTAURANT>
<NAME>Al Fresco Cafe</NAME>
<ADDRESS>3398 El Camino Real</ADDRESS>
</RESTAURANT>

</LIST>

--------------------------------------

html>
<head>
<title>Importing and Manipulating XML</title>
<script language="javascript">

/*************************************
DECLARE GLOBAL VARIABLES
*************************************/
var c
var d='';
var e='';
var f='';
var g='';
var xml_doc

/*************************************
MOZILLA - EXTRACT NODE INFORMATION
*************************************/
function readFileMoz()
{
node_list = xml_doc.getElementsByTagName("RESTAURANT")
for (i = 0; i <= node_list.length-1; i++)
{
c = node_list[i].childNodes[1].childNodes[0].nodeValue
d = node_list[i].childNodes[3].childNodes[0].nodeValue
//e = node_list[i].childNodes[5].nodeValue
//f = node_list[i].childNodes[7].nodeValue
//g = node_list[i].childNodes[9].nodeValue
alert("C = " + c + " D = " + d)
}
}


/*************************************
INTERNET EXPLORER - EXTRACT NODE INFORMATION
*************************************/
function readFileIE()
{
node_list = xml_doc.getElementsByTagName("RESTAURANT")

for (i = 0; i <= node_list.length-1; i++)
{
c = node_list[i].childNodes[0].childNodes[0].nodeValue
d = node_list[i].childNodes[1].childNodes[0].nodeValue
//e = node_list[i].childNodes[2].nodeValue
//f = node_list[i].childNodes[3].nodeValue
//g = node_list[i].childNodes[4].nodeValue
alert("C = " + c + " D = " + d)
}

}


/*************************************
This function loads the file.
*************************************/
function importXML(zFileName)
{
var moz = (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined');
var ie = (typeof window.ActiveXObject != 'undefined')

if (moz)
{
xml_doc = document.implementation.createDocument("", "", null)
xml_doc.onload = readFileMoz
}

else if (ie)
{
xml_doc = new ActiveXObject("Microsoft.XMLDOM")
xml_doc.onreadystatechange = function()
{
if (xml_doc.readyState == 4) setTimeout(readFileIE,0)
}
}

xml_doc.load(zFileName)

}

importXML('cust.xml');

</script>


</head>
<body>
</body>
</html>
----------------------------------------

Aaaaaahhhhhhhh........

It's all beginning to make sense now. The global variable I should have remembered. But I didn't know that all of the data had to be enclosed in a tag other than <xml>

Also, I still can't figure out why the syntax is the way it is with the childNodes...

if node_list starts with RESTAURANT, then the first set of childNodes would be NAME and ADDRESS, right? Then why the second set of childNode[0]'s. Having nodeValue makes sense.

In Mozilla, the XML file is read double-spaced, isn't it. That's why the arrays go 1,3,5,7, etc. In IE, they're single spaced, so the array goes 0,1,2,3,4, etc. Ahhh... I'm getting it now.

Hmmm... is there a way to get the elements by tag name instead of using the childNode method? Such as:



var node_list=xml_doc.getElementsByTagName('RESTAURANT');

var listName=node_list.getElementsByTagName('NAME');
var listAddress=node_list.getElementsByTagName('ADDRESS');

document.write('The name is ' + listName.nodeValue + ', and the address is ' + listAddress.nodeValue);


Would something similar to that work? Not that I'm complaining about you helping me or anything, but I was just curious. I've mastered HTML and nearly mastered JavaScript, so I want to move on to DOM/XML/XHTML. I'd appreciate any help you could give me.

Some answers to your queries:

If node_list is an array of RESTUARANT elements, then node_list[0].childNodes[0] is the first NAME element, and node_list[0].childNodes[0].childNodes[0] is the text node attached to that element, which contains the name of the first RESTURANT. The NAME node itself does not have a nodeValue - it is a container that can hold other nodes.

The reason that the indexing is different between IE and Mozilla is that the latter counts the line breaks in the XML file as whitespace nodes, whereas IE suppresses whitespace nodes.

To get the content of the nodes the way you describe you should really investigate the use of XSL. Can I suggest a visit to http://www.w3schools.com/ - they have a good range of XML and XSL tutorials.

patrick










privacy (GDPR)