Click to See Complete Forum and Search --> : Parse XML with JS help needed


bluejie
07-15-2008, 02:37 PM
I've got a XML-file: Click! (http://www.freewebs.com/bbson/MZ%20xml.xml)
And my code:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Naamloos document</title>
<script type="text/javascript">
function parseXML()
{
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);
return;
}
}
xmlDoc.async=false;
xmlDoc.load("http://www.freewebs.com/bbson/MZ%20xml.xml");
document.getElementById("Match id").innerHTML=xmlDoc.getElementsByTagName("Match id")[0].childNodes[0].nodeValue;
document.getElementById("Team teamName").innerHTML=xmlDoc.getElementsByTagName("Team teamName")[0].childNodes[0].nodeValue;
document.getElementById("Team goals").innerHTML=xmlDoc.getElementsByTagName("Team goals")[0].childNodes[0].nodeValue;
}
</script>
</head>


<body onload="parseXML()">
<h1>Wedstrijden</h1>
<p><b>Wedstrijd datum</b> <span id="Match id"></span><br />
<b>Team</b> <span id="Team teamName"></span>
<b>Goals</b> <span id="Team goals"></span>
</body>
</html>

I've got two problems:

1. The biggest: the data won't appear on the HTML output. Ithought something must be wrong with the ID's, but I've tried a lot of different ways.

In the XML it appears like this:
<Match id="251618390" date="2008-07-11 19:00" status="played" type="national_friendly" typeName="" typeId="">
The only thing I want is the ID. Some things I tried to use as ID:
Match id
id
Matchid
Match.id

But they just won't appear in the output

2. I've tried another XML-file...
Which is located here (http://www.w3schools.com/xml/note.xml). This works fine in IE, but in Firefox I get problems. I think the problem is here:
xmlDoc = document.implementation.createDocument("","",null);
But I'm not an expert so I don't know what is wrong.

Greetings,
Bluejie

bluejie
07-17-2008, 05:49 AM
someone plz?

Kostas Zotos
07-17-2008, 02:03 PM
Hi,

I can't access the first XML file (probably due to my firewall settings)..

Anyway,

At first: Normally for security reasons you cannot load an XML file which is located in a different domain than the one hosts your HTML file..

Secondly: I saw a small mistake in the way used to access the XML file element nodes..

I mean here:
[Given that the Element you want to parse is this (as you wrote in your first post)]:
<Match id="251618390" date="2008-07-11 19:00" status="played" type="national_friendly" typeName="" typeId="">

The element name is "Match" (NOT "Match id" -spaces not allowed in the node names- "id" is the name of the first attribute)
So is not correct to use "Match id" as the node name:
xmlDoc.getElementsByTagName("Match id")[0].childNodes[0].nodeValue; // Not specify correctly the node name (The right name is "Match" -id is the 1st attribute- )
-----------------------------------------

SUGGESTION:

Since I can't access the first XML file, I use a simple one to present an example of a possible way to parse your XML file (normally must be located in the same domain as your HTML):

Assume this is the XML file (named "MZ xml.xml"):
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<Data>
<Match id="251618390" date="2008-07-11 19:00" status="played" type="national_friendly" typeName="" typeId="">Node Value for Element 'Match' 1</Match>
<Team teamName="IronMen (Attribute of 1st 'Team' Element)" goals="8" date="2008-06-11 17:00">Node Value for Element 'Team' 1</Team>
<Team teamName="Eagles" goals="12" date="2008-07-11 19:00" /> <!-- An empty node, ends with /> (this is a comment) -->
</Data>

A possible HTML document to load the previous file (a variation of your HTML):
HTML:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Naamloos document</title>
<script type="text/javascript">
function parseXML()
{
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);
return;
}
}
xmlDoc.async=false;
xmlDoc.load("MZ xml.xml") // http://www.freewebs.com/bbson/MZ%20xml.xml");


//-------------------------------------------------- Parse the "Match" node ------------------------------------------------------------

// Get the node value of the first "Match" element: ( "Node Value for Element 'Match' 1" ):
document.getElementById("Match id").innerHTML=xmlDoc.getElementsByTagName("Match")[0].childNodes[0].nodeValue;

// Get the attribute: "date" of the first "Match" element: ( "2008-07-11 19:00")
document.getElementById("Match_Date").innerHTML=xmlDoc.getElementsByTagName("Match")[0].getAttribute("date")


//----------------------------------------------- Parse the 1st "Team" node ------------------------------------------------------------

// Get the attribute: "teamName" of the first "Team" element:
document.getElementById("Team teamName").innerHTML=xmlDoc.getElementsByTagName("Team")[0].getAttribute("teamName");

// Get the attribute: "goals" of the first "Team" element:
document.getElementById("Team goals").innerHTML=xmlDoc.getElementsByTagName("Team")[0].getAttribute("goals");

// Get the node value of the first "Team" element: ( "Node Value for Element 'Team' 1" ):
// document.getElementById("Team goals").innerHTML=xmlDoc.getElementsByTagName("Team")[0].childNodes[0].nodeValue;


//---------------------------------------------- Parse the 2nd "Team" node ----------------------------------------------------------
// ( For demonstration purposes )

// NOTE: the second "Team" element is an emtpy node (has only attributes)
// So has no meaning to get its element nodeValue (is empty) with the following:
//var Value=xmlDoc.getElementsByTagName("Team")[1].childNodes[0].nodeValue; // Returns an error or empty string


// You may get its attributes as usual, for example:
Value= xmlDoc.getElementsByTagName("Team")[1].getAttribute("teamName"); // Eagles
alert("Second \"Team\" elements \"teamName\" Attribute= "+Value)

}


</script>

</head>


<body onload="parseXML()">
<h1>Wedstrijden</h1>

<b>Wedstrijd datum:</b> <span id="Match id"></span><br />
<b>Date:</b> <span id="Match_Date"></span><br />
<b>Team:</b> <span id="Team teamName"></span><br />
<b>Goals:</b> <span id="Team goals"></span>


</body>
</html>

Also an advise: is better to avoid spaces in names of files and IDs properties in HTML and use eg. the underscore ( _ ) instead :)
(Of course spaces are not permitted in node names in XML documents)

PS: Regarding your second problem.. I can load the XML normally in IE, Netscape and Firefox..

Regards!

Kostas

bluejie
07-30-2008, 06:44 AM
Thank you for your help. But I still don't understand how I can show the second team. And if I want to show de data in a tabel I get something weird. This is my tabel:
Click! (http://www.freewebs.com/bbson/myxml.html)
And this is the code of the tabel:

<table width="200" border="1">
<tr>
<td colspan="4"><span id="Match Date"></span></td>
</tr>
<tr>
<td><span id="Team teamName"></span></td>
<td><span id="Team goals"></span></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>

Why is it showing so weird?

Kostas Zotos
07-30-2008, 03:45 PM
Hi,
your welcome!

The xmlDoc.getElementsByTagName("Team") returns an array with all "Team" xml nodes..

To access the first element use (has array index=0):
xmlDoc.getElementsByTagName("Team")[0]

To access the second element use (has array index=1):
xmlDoc.getElementsByTagName("Team")[1]

Just provide the correct index


So to access the second team may use:

// Get the attribute: "teamName" of the 2nd "Team" element:
document.getElementById("Team teamName").innerHTML=xmlDoc.getElementsByTagName("Team")[1].getAttribute("teamName");

// Get the attribute: "goals" of the 2nd "Team" element:
document.getElementById("Team goals").innerHTML=xmlDoc.getElementsByTagName("Team")[1].getAttribute("goals");

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

To dynamically create an array from your xml may run a "for" loop for all the child nodes you want. For example (run the next to create an array):

JavaScript:
var TeamNodes=xmlDoc.getElementsByTagName("Team")

var TableCode="";

TableCode='<table width="200" border="1">;

for (var i=0; i<TeamNodes.length; i++){
var Name=TeamNodes[i].getAttribute("teamName");
var Goals=TeamNodes[i].getAttribute("goals");
var DateVal=TeamNodes[i].getAttribute("date");
TableCode+='<tr><td>'+Name+'</td><td>'+Goals+'</td><td>'+DateVal+'</td></tr>'
}

TableCode+='</table>'

document.getElementById("TableDiv").innerHTML=TableCode


In your html must exist a div tag for your table like eg:
HTML:
<div name="TableDiv" id="TableDiv">
</div>

---------------
The above is just to get an idea. You need to ajust it in your files and html

Cheers!

Kostas

bluejie
07-31-2008, 06:10 AM
Thank you for your response! It helped a lot. But I still don't understand the part with the table. Could you explain that a bit more?

And I've another problem. Until now I haven't worked with the actual XML-file. That's located here (http://www.managerzone.com/xml/team_matchlist.php?sport_id=1&team_id=122&match_status=1&limit=50)

I've changed the url in my html-file, but then it isn't working.

html with the right url: Click (http://www.freewebs.com/bbson/xml1.html)
html with the url I've used until now: Click (http://www.freewebs.com/bbson/xml.html)

And something else, how can I make it like that, so that the parser will automatically parse more matches if there are more?

I've got this now:

// Get the node value of the first "Match" element: ( "Node Value for Element 'Match' 1" ):
document.getElementById("Match id").innerHTML=xmlDoc.getElementsByTagName("Match")[0].childNodes[0].nodeValue;

// Get the attribute: "date" of the first "Match" element: ( "2008-07-11 19:00")
document.getElementById("Match Date").innerHTML=xmlDoc.getElementsByTagName("Match")[0].getAttribute("date")


//----------------------------------------------- Parse the 1st "Team" node ------------------------------------------------------------

// Get the attribute: "teamName" of the first "Team" element:
document.getElementById("Team teamName h").innerHTML=xmlDoc.getElementsByTagName("Team")[0].getAttribute("teamName");

// Get the attribute: "goals" of the first "Team" element:
document.getElementById("Team goals h").innerHTML=xmlDoc.getElementsByTagName("Team")[0].getAttribute("goals");

// Get the attribute: "teamName" of the 2nd "Team" element:
document.getElementById("Team teamName a").innerHTML=xmlDoc.getElementsByTagName("Team")[1].getAttribute("teamName");

// Get the attribute: "goals" of the 2nd "Team" element:
document.getElementById("Team goals a").innerHTML=xmlDoc.getElementsByTagName("Team")[1].getAttribute("goals");

I've to change this:
document.getElementById("Match Date").innerHTML=xmlDoc.getElementsByTagName("Match")[0].getAttribute("date")

Into this:
document.getElementById("Match Date").innerHTML=xmlDoc.getElementsByTagName("Match")[1].getAttribute("date")

But then I've to give it another ID, otherwise it will automatically take the second one. How can I make it that I dont have to make new ID's, but the parser makes new ones?

Kostas Zotos
08-01-2008, 01:17 PM
And I've another problem. Until now I haven't worked with the actual XML-file. That's located here
I've changed the url in my html-file, but then it isn't working.
Normally for security reasons you cannot load an XML file which is located in a different domain (server) than the one hosts your HTML file..
If this is the case, you have to use server side solution (eg. php) to access the remote xml file.

Rregarding the code for table:
Firstly, In this line I had missed a closing single quote: TableCode='<table width="200" border="1">'

Please read the code comments (I've tried to explain in more details the code parts) :
JS:
/*
The next JS reads the "Team" elements of our loaded xml file and dynamically (at run time)
creates a html table to display selected info from loaded data.
A "for" loop runs for every found "Team" node, and gets the appropriate values which incorporate in a string (text) variable.
This variable will replace the "innerHTML" of our placeholder (a simple "div" html tag) so that the generated
table becomes part (and displayed) of our html document
*/

var TeamNodes=xmlDoc.getElementsByTagName("Team") // Returns an array of all "Team" nodes of the .xml file

// How to access specific nodes:
// TeamNodes[0] => the 1st "Team" element (the array is zero based)
// TeamNodes[1] => the 2nd "Team" element
// and so on...


var TableCode=""; // A text variable to keep the generated HTML code

TableCode='<table width="400" border="1">' // The table start tag


// Run the "for" loop to process all array's elements ("Team" nodes)

for (var i=0; i<TeamNodes.length; i++){ // TeamNodes.length => the total number of array's elements

// Get the values we want (in these case all are attributes of our "Team" element)

var Name=TeamNodes[i].getAttribute("teamName"); // TeamNodes[i] => is the current element
var Goals=TeamNodes[i].getAttribute("goals");
var DateVal=TeamNodes[i].getAttribute("date");

// if want to get a nodeValue (not attribute) then use: var Value=TeamNodes[i].nodeValue
// NOTE: The node should have a nodeValue (must not empty) for the previous to have meaning,
// eg. <node Attr="This is an attribute">This is nodeValue</node>

// For each "Team" node, add a table row with 3 columns (Name, Goals and DateVal hold actual values -the attributes values- read from the xml file)
// the HTML code line generated has the form: <tr><td>Team Name</td><td>8</td><td>2008-07-22 19:00</td></tr>

TableCode+= '<tr><td>' + Name + '</td><td>' + Goals + '</td><td>' + DateVal + '</td></tr>\n'

}


TableCode+='</table>' // Once the "for" finished, we add the close tag of table

document.getElementById("TableDiv").innerHTML=TableCode // Write the generated code to our document (replace the "TableDiv" contents)

-----------------------------------------------------
Regarding the auto generation of IDs and how to parse all "Match" nodes of your file
(In general when use a "for" loop to parse all the children of an element, you don't need to know the exactly number of children nodes..
just the "for" runs for all of the given node list or array children, and you can add or remove data from your xml without problem)..

Here is a complete example of parsing all "Match" nodes of the xml and generating
html table(s) to display the input xml data. (Every "Match" element shown in its own array -for clarification reasons- ):

1) Save this .xml code in a file named "Team.xml":
(This may content any number of "Match" elements, and every "Match" element may have any number of children..
here i use this xml snippet as an example)
<?xml version="1.0" encoding="utf-8" ?>
<ManagerZone_MatchList>
<Match id="263736548" date="2008-07-29 19:00" status="played" type="national_friendly" typeName="" typeId="">
<Team field="home" goals="7" teamId="122" teamName="Netherlands" countryShortname="" />
<Team field="away" goals="0" teamId="855911" teamName="Ukraine" countryShortname="" />
</Match>
<Match id="263736544" date="2008-07-25 11:00" status="played" type="national_friendly" typeName="" typeId="">
<Team field="home" goals="3" teamId="122" teamName="Netherlands" countryShortname="" />
<Team field="away" goals="0" teamId="498688" teamName="Ecuador" countryShortname="" />
</Match>
<Match id="252179958" date="2008-07-22 19:00" status="played" type="national_friendly" typeName="" typeId="">
<Team field="home" goals="3" teamId="122" teamName="Netherlands" countryShortname="" />
<Team field="away" goals="3" teamId="106" teamName="Czech Republic" countryShortname="" />
</Match>
<Match id="251618380" date="2008-07-18 19:00" status="played" type="national_friendly" typeName="" typeId="">
<Team field="home" goals="2" teamId="122" teamName="Netherlands" countryShortname="" />
<Team field="away" goals="3" teamId="103" teamName="Belgium" countryShortname="" />
</Match>
<Match id="251618386" date="2008-07-15 19:00" status="played" type="national_friendly" typeName="" typeId="">
<Team field="home" goals="3" teamId="103" teamName="Belgium" countryShortname="" />
<Team field="away" goals="2" teamId="122" teamName="Netherlands" countryShortname="" />
</Match>
</ManagerZone_MatchList>

2) Paste this HTML to a new document (based on your initial HTML file):
(The JS part, read the xml, and create tables to show the input xml data)
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Naamloos document</title>


<script type="text/javascript">


function parseXML()
{
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);
return;
}
}

xmlDoc.async=false;
// xmlDoc.load("http://www.freewebs.com/bbson/MZ%20xml.xml");
xmlDoc.load("Team.xml")



// ---------------------- Process the load xml file (to generate HTML code, to display the xml data on tables)---------------------------------

var Matches=xmlDoc.getElementsByTagName("Match") // An array of all "Match" nodes


var OutputCode="" // Will keep the HTML code (which will be generated from this script)


for (var a=0; a<Matches.length; a++) { // Run a "for" loop to read all "Match" nodes and their children ("Team" nodes)

var CurrentMatch=Matches[a]

// Read the various "Match" element's attributes
var id=CurrentMatch.getAttribute("id") // OR: CurrentMatch.attributes[0].value
var date=CurrentMatch.getAttribute("date")
var status=CurrentMatch.getAttribute("status")
var type=CurrentMatch.getAttribute("type")


// The match info (and tables declaration)
OutputCode+='<br/><br/> <b>' + (a+1) + ') Match id: </b>' + id + '<br/><b> &nbsp; &nbsp; Status: </b>' + status + '<br/><b> &nbsp; &nbsp; Type: </b>' + type
OutputCode+='<br/><br/> <table border="1" width="400" borderColor="#445566" cellspacing="0" cellpadding="10" style="background:#d7dedf; font:12px verdana; border-collapse:collapse">\n\n'


// The "Date" cell
OutputCode+='<tr><th align="center" colspan="4"> Date: &nbsp; ' + date + '</th></tr>\n'


// The Titles cells (Field, Goals, Team id, Team)
OutputCode+='<tr align="center" style="background:#447788; color:#ffffff"><th>Field</th><th>Goals</th><th>Team Id</th><th>Team Name</th></tr>\n'



// A second nested "for" to process the "Match" 's children ("Team" nodes)
var Teams=CurrentMatch.childNodes

for (var b=0; b<Teams.length; b++) {

if (Teams[b].nodeType==1 ) { // If child is an element node (to avoid empty or text nodes)
var field=Teams[b].getAttribute("field")
var goals=Teams[b].getAttribute("goals")
var teamId=Teams[b].getAttribute("teamId")
var teamName=Teams[b].getAttribute("teamName")

// Write each "Team" statistics
OutputCode+='<tr align="center"><td>' + field + '</td><td>' + goals + '</td><td>' + teamId + '</td><td>' + teamName + '</td></tr>\n'
}

}


OutputCode+='</table><br/>\n\n' // Close the table for the current match (the same repeated for every "Match" node)

} // End of : " for (var a=0; a..."

// ---------------------- Process the load xml file (to generate HTML code, to display the xml data on tables) (END) ---------------------------



// Replace the contents of our placeholder html div
document.getElementById("TableDiv").innerHTML=OutputCode


}

</script>


</head>



<body style="font:13px verdana" onload="parseXML()">

<h1>Wedstrijden</h1>

<hr/>
<h2>Match List:</h2>


<div name="TableDiv" id="TableDiv">
<!-- This will replaced by the generated code (the tables) -->
</div>


</body>
</html>

NOTE: This based exclusively on JavaScript, to format the html document, however by using for example an .xsl (xml Stylesheet ) file
(either declared it directly into the .xml file or loaded with javascript) is a better approach..
(This requires of course a basic knowledge of xpath, xslt)

Regards!

Kostas

bluejie
08-26-2008, 02:50 PM
Thank you very much!
I'll change the table in the javascript and write if there is still something going wrong. (until now nothing!)

again thanks!

Kostas Zotos
08-26-2008, 08:41 PM
Don't mention it!

I'll change the table in the javascript and write if there is still something going wrong. (until now nothing!)
Ok, I am glad If I can help (just I am a bit more busy lately and I can't be so active or frequent visitor as I would like)

Best regards!

Kostas