PDA

View Full Version : Problems with xmlDocElement.item(i).text / XML and Javascript



keisuke_z
Apr 11th, 2007, 01:34 AM
Hi guys,

Okay, so I'm definitely a newb when it comes to XML and Javascript. I'm running into errors when I encounter an empty XML element.

So here's what I'm trying to do: My data is stored in an XML file (Parent: Document, 3 Children per Parent: ID, URL, Title), and I am using Javascript to parse the XML and using document.write() statements, I create hyperlinks in my index.HTML, where I call the Javascript. It's essentially an A-Z list of documents - around 1000+ entries. The XML structure is like:

<document>

<doc_id></doc_id>

<doc_title></doc_title>

<doc_url></doc_url>
</document>

So the XML is a huge list of documents, in order from A-Z. Between each "letter group" is:

<document>

<doc_id>New</doc_id>

<doc_title>A</doc_title>

<doc_url></doc_url>
</document>

Where the letter changes for each "letter group". This indicates to the Javascript that a new section needs to be created in the HTML --> this in turn should call different document.write statements that write the various <div>, etc tags.

I know this probably isn't the best XML structure, but it's unfortunately all I have to work with (client/system constraints - the XML is generated from a 3rd party report program). Anyway, so throughout the XML, there may scenarios where the <doc_url> or <doc_title> elements are empty. When that happens, the Javascript sees the object as "undefined" and errors start showing up in IE. The code I'm using is below... I've commented it as best I can - I really hope you guys can help me out!


var filePath = "xml/sourcedata.xml";
var sortTagname = "document_id";
var urlTagname = "ad-hoc_url";
var descTagname = "document_title";

//Instantiate XML Document;
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.load(filePath);
xmlError = xmlDoc.parseError;

if (xmlError!=0)
{
document.write(xmlError.reason);
}
else
{
//select data containing the URLs & document titles by specific nodenames;
var objDocID = xmlDoc.getElementsByTagName(sortTagname);
var objDocURL = xmlDoc.getElementsByTagName(urlTagname);
var objDocTitle = xmlDoc.getElementsByTagName(descTagname);

//determines how many times to loop;
var numNodes = objDocTitle.length;

//begin alpha listing;

var noDocsMsg = "No documents exist for this entry";
var newsectionflag = 0;

document.write("<div class=\"alphamarginsetup\">"); //open all documents <div>

//loop: for every node that was selected, concatenate the URLs & document titles into an <a href> tag
for (i=0; i<=numNodes; i++)
{
//error handling: if URL element is empty/null/undefined, then go to next node
if(!objDocURL.item(i)|!objDocID.item(i)|!objDocTitle.item(i))
{
i++;
}
else
{ //gets data from nodes and stores in variable
currDocID = objDocID.item(i).text;
currURL = objDocURL.item(i).text;
currTitle = objDocTitle.item(i).text;

switch(currDocID)
{
case "New":
newsectionflag++;
//check if no documents flag is set --> when new section is created twice in a row
if(newsectionflag>=2)
{
document.write("<br><div class=\"nodocsmsg\">" + noDocsMsg + "</div><br>");
}
//create section header --> No line break above first header
if(currTitle!="A")
{
document.write("<br>");
}
document.write("<a class=\"sectiontitle\" name=\""+currTitle+"\">");
document.write("<div class=\"sectiontitle\">"+currTitle+"</div>");
document.write("</a><br>");
document.write("<a class=\"backtotop\" href=\"#\">...back to top</a>");
break;

default:
document.write("<a class=\"alphalinks\" target=\"_self\" href=\"edmccsmop01\\ace\\" + currURL + "\">" + currTitle + "</a><br>");
newsectionflag = 0;
}//end switch
//}//end if..else
}//end for
document.write("</div>"); //closes all documents <div>
}//end master if..else

keisuke_z
Apr 11th, 2007, 07:52 AM
Anybody?

david_kw
Apr 11th, 2007, 08:24 AM
Well I looked at it for a bit. If I comment in the end-if curly bracket it seems to largely work so I'm not sure what your problem is. The one other thing I noticed is you had

for (i=0; i<=numNodes; i++)

when it really should be

for (i=0; i<numNodes; i++)

Anyway, I rewrote a few things to help me understand it better, but again I'm not sure the problem. It seemed to work fine dealing with missing elements. Here is the XML file I used to test it.



<documents>
<document>
<document_id>New</document_id>
<document_title>A</document_title>
<ad-hoc_url></ad-hoc_url>
</document>
<document>
<document_id>55</document_id>
<document_title>A Tree Grows in Brooklin</document_title>
<ad-hoc_url>http://tree.in.com</ad-hoc_url>
</document>
<document>
<document_id>56</document_id>
<document_title></document_title>
<ad-hoc_url>http://blank.com</ad-hoc_url>
</document>
<document>
<document_id>57</document_id>
<document_title>An Ant</document_title>
<ad-hoc_url>http://an.ant.com</ad-hoc_url>
</document>
<document>
<document_id>New</document_id>
<document_title>B</document_title>
<ad-hoc_url></ad-hoc_url>
</document>
<document>
<document_id>65</document_id>
<document_title>Beware the Creeper!</document_title>
<ad-hoc_url>http://be.ware.creeper.com</ad-hoc_url>
</document>
</documents>


And here is my altered code. If you want to try it you need to switch the filePath back to

var filePath = "xml/sourcedata.xml";

like you had it in your version.



<script type="text/javascript">
var filePath = "test2.xml";
var sortTagname = "document_id";
var urlTagname = "ad-hoc_url";
var descTagname = "document_title";

//Instantiate XML Document;
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(filePath);
xmlError = xmlDoc.parseError;

if (xmlError!=0)
{
document.write(xmlError.reason);
}
else
{
//select data containing the URLs & document titles by specific nodenames;
var objDocID = xmlDoc.getElementsByTagName(sortTagname);
var objDocURL = xmlDoc.getElementsByTagName(urlTagname);
var objDocTitle = xmlDoc.getElementsByTagName(descTagname);

//determines how many times to loop;
var numNodes = objDocTitle.length;

//begin alpha listing;

var noDocsMsg = "No documents exist for this entry";
var newsectionflag = 0;

document.write("<div class=\"alphamarginsetup\">"); //open all documents <div>

//loop: for every node that was selected, concatenate the URLs & document titles into an <a href> tag
for (i=0; i<numNodes; i++)
{
currDocID = objDocID.item(i).text;
currURL = objDocURL.item(i).text;
currTitle = objDocTitle.item(i).text;
//error handling: if Title element is empty/null/undefined, then go to next node
if (!currTitle) {
continue;
} else {
switch(currDocID)
{
case "New":
newsectionflag++;
//check if no documents flag is set --> when new section is created twice in a row
if(newsectionflag>=2)
{
document.write("<br><div class=\"nodocsmsg\">" + noDocsMsg + "</div><br>");
}
//create section header --> No line break above first header
if(currTitle!="A")
{
document.write("<br><a class=\"backtotop\" href=\"#\">...back to top</a><br>");
document.write("<br>");
}
document.write("<a class=\"sectiontitle\" name=\""+currTitle+"\">");
document.write("<div class=\"sectiontitle\">"+currTitle+"</div>");
document.write("</a><br>");
break;

default:
document.write("<a class=\"alphalinks\" target=\"_self\" href=\"edmccsmop01\\ace\\" + currURL + "\">" + currTitle + "</a><br>");
newsectionflag = 0;
}//end switch
}
}//end for
document.write("<br><a class=\"backtotop\" href=\"#\">...back to top</a><br>");
document.write("<br>");
document.write("</div>"); //closes all documents <div>
}//end master if..else
</script>


No idea if that helps or not. Good luck.

david_kw

keisuke_z
Apr 11th, 2007, 06:44 PM
Hi David,

Actually, I need to keep the "<=" otherwise it seems to miss the last few pieces of data. However - the modifications you made to the code helped me fix the error I was getting! I had to change the "if..else" to:


if ((!currTitle | !currURL) && currDocID!="New") {
continue;
} else {

To make sure that I didn't lose my section dividers, but yea now it works error-free. It had previously been creating links with just spaces - that was the error that happened when there were empty elements in the XML.

Anyway, THANKS so much!
Kei


Well I looked at it for a bit. If I comment in the end-if curly bracket it seems to largely work so I'm not sure what your problem is. The one other thing I noticed is you had

for (i=0; i<=numNodes; i++)

when it really should be

for (i=0; i<numNodes; i++)

Anyway, I rewrote a few things to help me understand it better, but again I'm not sure the problem. It seemed to work fine dealing with missing elements. Here is the XML file I used to test it.



<documents>
<document>
<document_id>New</document_id>
<document_title>A</document_title>
<ad-hoc_url></ad-hoc_url>
</document>
<document>
<document_id>55</document_id>
<document_title>A Tree Grows in Brooklin</document_title>
<ad-hoc_url>http://tree.in.com</ad-hoc_url>
</document>
<document>
<document_id>56</document_id>
<document_title></document_title>
<ad-hoc_url>http://blank.com</ad-hoc_url>
</document>
<document>
<document_id>57</document_id>
<document_title>An Ant</document_title>
<ad-hoc_url>http://an.ant.com</ad-hoc_url>
</document>
<document>
<document_id>New</document_id>
<document_title>B</document_title>
<ad-hoc_url></ad-hoc_url>
</document>
<document>
<document_id>65</document_id>
<document_title>Beware the Creeper!</document_title>
<ad-hoc_url>http://be.ware.creeper.com</ad-hoc_url>
</document>
</documents>


And here is my altered code. If you want to try it you need to switch the filePath back to

var filePath = "xml/sourcedata.xml";

like you had it in your version.



<script type="text/javascript">
var filePath = "test2.xml";
var sortTagname = "document_id";
var urlTagname = "ad-hoc_url";
var descTagname = "document_title";

//Instantiate XML Document;
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(filePath);
xmlError = xmlDoc.parseError;

if (xmlError!=0)
{
document.write(xmlError.reason);
}
else
{
//select data containing the URLs & document titles by specific nodenames;
var objDocID = xmlDoc.getElementsByTagName(sortTagname);
var objDocURL = xmlDoc.getElementsByTagName(urlTagname);
var objDocTitle = xmlDoc.getElementsByTagName(descTagname);

//determines how many times to loop;
var numNodes = objDocTitle.length;

//begin alpha listing;

var noDocsMsg = "No documents exist for this entry";
var newsectionflag = 0;

document.write("<div class=\"alphamarginsetup\">"); //open all documents <div>

//loop: for every node that was selected, concatenate the URLs & document titles into an <a href> tag
for (i=0; i<numNodes; i++)
{
currDocID = objDocID.item(i).text;
currURL = objDocURL.item(i).text;
currTitle = objDocTitle.item(i).text;
//error handling: if Title element is empty/null/undefined, then go to next node
if (!currTitle) {
continue;
} else {
switch(currDocID)
{
case "New":
newsectionflag++;
//check if no documents flag is set --> when new section is created twice in a row
if(newsectionflag>=2)
{
document.write("<br><div class=\"nodocsmsg\">" + noDocsMsg + "</div><br>");
}
//create section header --> No line break above first header
if(currTitle!="A")
{
document.write("<br><a class=\"backtotop\" href=\"#\">...back to top</a><br>");
document.write("<br>");
}
document.write("<a class=\"sectiontitle\" name=\""+currTitle+"\">");
document.write("<div class=\"sectiontitle\">"+currTitle+"</div>");
document.write("</a><br>");
break;

default:
document.write("<a class=\"alphalinks\" target=\"_self\" href=\"edmccsmop01\\ace\\" + currURL + "\">" + currTitle + "</a><br>");
newsectionflag = 0;
}//end switch
}
}//end for
document.write("<br><a class=\"backtotop\" href=\"#\">...back to top</a><br>");
document.write("<br>");
document.write("</div>"); //closes all documents <div>
}//end master if..else
</script>


No idea if that helps or not. Good luck.

david_kw

david_kw
Apr 11th, 2007, 07:03 PM
Actually what you should probably do is



var numNodes= xmlDoc.getElementsByTagName("document").length;

for (int i = 0; i < numNodes; i++) {


That would be a more accurate number since sometimes fields are empty.

And you are welcome. :)

david_kw