Click to See Complete Forum and Search --> : [Resolved] Begginner XML Parsing: for loop issue


walfredo
06-01-2009, 10:22 AM
Good morning,

As a graphic designer turned web developer, I have recently began incorporating XML technology into my company's website.

I have run into a bit of a snag however when it comes to parsing an XML file.

Brief synopsis:
I am calling a javascript function from an html webpage to parse through an XML file to dynamically populate the webpage with information.

I have narrowed my issue down to this problem:
My for loop is prematurely stopping and will not execute any code after the loop. The loop reads all of the nodes I want it to, but then ends/errors out when it cannot find anymore. Explaination below:

My XML file:
<?xml version="1.0"?>
<ob>

<tourdate>SEPT. XX - XX, 2010</tourdate>
<tourdate>SEPT. XX - OCT. XX, 2010</tourdate>

<pricetitle>STARTING AT:</pricetitle>
<price>$X,XXX</price>

<pricedetail>BALCONY STATEROOM</pricedetail>
<pricedetail>Category DD Deck 5:</pricedetail>
<pricedetail>Double.......$X,XXX</pricedetail>
<pricedetail>Single.......$X,XXX</pricedetail>

<pricedetail>OCEANVIEW STATEROOM</pricedetail>
<pricedetail>Category BD Deck 8:</pricedetail>
<pricedetail>Double.......$X,XXX</pricedetail>
<pricedetail>Single.......$X,XXX</pricedetail>

<priceinfo>Triple subject to availability</priceinfo>
<priceinfo>Gold Leaf Service available upon request- add $XXX per person</priceinfo>

<finalpaytitle>FINAL PAYMENT:</finalpaytitle>
<finalpay>95 days prior to departure</finalpay>

<refundtitle>FULL REFUND:</refundtitle>
<refund>Up to 96 days prior to departure</refund>






<tourcolor>green</tourcolor>

<tourtitle>Austria &amp; Germany</tourtitle>
<toursubtitle>with Oberammergau Passion Play</toursubtitle>

<day1>Day 1: Fly to Munich</day1>
<day1text>Relax and enjoy the overnight flight to Germany</day1text>
<day1meals>None</day1meals>

<day2>Day 2: European Welcome</day2>
<day2text>Upon arrival in Munich, we meet our European Guide and Driver. Enjoy the leisurely drive to the mountainous region of Kitzbuhel, Austria. Unpack and settle in for four delightful nights at our comfortable hotel. Tonight we are guests at a special welcome dinner.</day2text>
<day2meals>Dinner</day2meals>

<day3>Day 3: Innsbruck</day3>
<day3text>Our sightseeing today features the Tyrolean ski capital of Innsbruck. Surrounded by dramatic mountain landscapes and picturesque villages, Innbruck has been the site of two Winter Olymics, most recently in 1976. During our visit to Innsbruck we have time to browse and shop as well as look for exquisite pieces of Austrian Crystal. Sightseeing includes the Court Church, one of the most impressive monuments in Europe. We also see the Goldenes Dachl (Golden Roof), an ornate stone balcony covered by gilded copper tiles, built in the 15th century. Later, we visit historical Tratzberg Castle which is perched above the picturesque Inn Valley. Enjoy a guided tour of this beautiful 16th century castle which at one time was owned by Hapsburg Emperor Maximilian I. We return to our hotel for dinner.</day3text>
<day3meals>Breakfast, Dinner</day3meals>



</ob>


My javascript code:
function parseXMLprice()
{
var doc_name=window.location.search.substring(1);

var price_title;
var price;
var price_detail;

var price_info;

var finalpay_title;
var final_pay;

var refund_title;
var refund;

try
{
if (window.ActiveXObject)
{
var errorHappendHere = "Check Browser and security settings";
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load("xml/" + doc_name + ".xml");
}
else if(window.XMLHttpRequest)
{
var errorHappendHere = "Error handling XMLHttpRequest request";
var d = new XMLHttpRequest();
d.open("GET", "xml/" + doc_name + ".xml", false);
d.send(null);
xmlDoc=d.responseXML;
}
else {
var errorHappendHere = "Error.";
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.async=false;
xmlDoc.load("xml/" + doc_name + ".xml");
}
}
catch(e)
{
alert(errorHappendHere);
}

var x=xmlDoc.documentElement.childNodes; // x.length = 61

document.write("<ul>");
price_title=xmlDoc.getElementsByTagName("pricetitle")[0].firstChild.nodeValue;
document.write("<li><span class=\"b0\" style=\"padding:0px\">" + price_title + "</span></li>");
price=xmlDoc.getElementsByTagName("price")[0].firstChild.nodeValue;
document.write("<li><h2 class=\"dgold\">" + price + "</h2></li>");
document.write("</ul>");


document.write("<ul class=\"medgray b0\" style=\"line-height: 0.8125em\">");
for (i=0;i<x.length;i++)
{
price_detail=xmlDoc.getElementsByTagName("pricedetail")[i].firstChild.nodeValue;
document.write("<li><span style=\"padding:0px\">" + price_detail + "</span></li>");
}

//for loop errors out after 8 iterations and function seems to end here

document.write("</ul>");


document.write("<ul class=\"lightgray\" style=\"line-height: 0.8125em; padding-top: 10px\">");
for (j=0;j<x.length;j++)
{
price_info=xmlDoc.getElementsByTagName("priceinfo")[j].firstChild.nodeValue;
document.write("<li><span class=\"b0\" style=\"padding:0px\">" + price_info + "</span></li>");
}
document.write("</ul>");
}


The Problem:
x.length (after being loaded by x=xmlDoc.documentElement.childNodes;
) is showing a value of 61, which is expected. The problem is that my loop wants to run 61 times, but after the 8th run through, does not find any more "pricedetail" nodes and then stops, and will not run any of the code after the loop.

My first thought would be to set x=the number of "pricedetail" nodes (instead of the number of nodes in the entire document) but I do not know the syntax of how to do that. I know what the problem is, I just dont know how to fix it. I also considered a "break" and "continue" statement in the loop but again, do not know exactly where to start.

Any help is greatly appreciated. Keep in mind that I am a beginner with javascript so please speak slowly =)

Kor
06-01-2009, 10:55 AM
First at all: childNodes method will count the textNodes and (in Mozilla) the empty spaces as well. IE counts only some of the empty spaces. Thus, counting the childNodes is not a reliable cross browser method. In fact... what kind of nodes to you want to count?

On the other hand, what else do you expect? You have 8 <pricedetail> tags, so that it is logical for the loop to stop and give you an error while trying to find the 9th non-existent tag.

And, finally, your XML structure is not quite well formatted, logically speaking. Try to build a branch tree structure, not an endless list of first level tag nodes. Something like:

<?xml version="1.0"?>
<document>

<product>
<name>product 1</name>
<price>8.00</price>
<detail> some detail </detail>
</product>

<product>
<name>product 2</name>
<price>3.00</price>
<detail> some detail </detail>
</product>

<product>
<name>product 3</name>
<price>21.00</price>
<detail> some detail </detail>
</product>

</document>

walfredo
06-01-2009, 10:57 AM
Well after some digging I was able to figure out the syntax of what I was trying to do.

var x=xmlDoc.documentElement.childNodes;


now becomes...

var x=xmlDoc.getElementsByTagName("pricedetail");



Which allows my loop to only cycle the 8 times that is needed, and will change the number of iterations depending on the number of "pricedetail" nodes in the host xml file.

walfredo
06-01-2009, 11:01 AM
Hi Kor,

Thanks for the reply. I am trying to count the number of "pricedetail" child elements of the root node, so that I can use that number to set the scope of my for loop. The change above seems to have worked.

I also tested everything in Firefox and it seems to work fine. However, I do realize (as an extreme beginner) that the way I have written the code may not be the ideal way to do it, so in that area, I am open to any suggestions or tips you may have.

Also, when the loop errors out, it is not executing the code that I have after the loop (which coincidentally happens to be ANOTHER loop! hah!).

And finally, I know my XML structure is a bit less organized than it could be, but it's for simplicity while I learn how to parse files.

Thanks!

jkmyoung
06-01-2009, 11:02 AM
var x=xmlDoc.documentElement.getElementsByTagName("pricedetail");

You don't use x anywhere except for the length correct?
Maybe even use
var x=xmlDoc.documentElement.getElementsByTagName("pricedetail").length;
and replace x.length with x.

--
darn, I'm a slow poster.

walfredo
06-01-2009, 11:07 AM
var x=xmlDoc.documentElement.getElementsByTagName("pricedetail");

You don't use x anywhere except for the length correct?
Maybe even use
var x=xmlDoc.documentElement.getElementsByTagName("pricedetail").length;
and replace x.length with x.


Whats the difference between:
x=xmlDoc.documentElement.getElementsByTagName("pricedetail");

and (if any?):
x=xmlDoc.getElementsByTagName("pricedetail");

walfredo
06-01-2009, 12:09 PM
Im not sure how to flag this post as resolved so hopefully this works