<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Musings&#60;Biefeld&#62; &#187; JScript</title>
	<atom:link href="http://sbiefeld.com/tag/jscript/feed/" rel="self" type="application/rss+xml" />
	<link>http://sbiefeld.com</link>
	<description>- curiosities of development, life, the universe and everything -</description>
	<lastBuildDate>Thu, 17 Nov 2011 04:01:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>XML Parsing with JavaScript</title>
		<link>http://sbiefeld.com/2008/03/quick-and-dirty-xml-parsing-with-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=quick-and-dirty-xml-parsing-with-javascript</link>
		<comments>http://sbiefeld.com/2008/03/quick-and-dirty-xml-parsing-with-javascript/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 05:33:37 +0000</pubDate>
		<dc:creator>Sean Biefeld</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JScript]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[rss parsing]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[xml parsing]]></category>

		<guid isPermaLink="false">http://sbiefeld.com/?p=9</guid>
		<description><![CDATA[A few weeks ago I was looking for a solution to parse an XML file into XHTML. This can be helpful if you want to store data for your web site in XML and want a quick scripting language to access it and parse it, this technique can be used to parse RSS since it [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago I was looking for a solution to parse an XML file into XHTML.  This can be helpful if you want to store data for your web site in XML and want a quick scripting language to access it and parse it, this technique can be used to parse RSS since it is XML.</p>
<p>I spent a couple of hours scouring the web for information.  I was able to gather bits and pieces from different ends of the Internet to come up with a solution.</p>
<p>First let&#8217;s look at the XML document.  The data in my XML file contains multiple choice questions and their answers.  This means I will need to parse out the data and form a label for the question and radio buttons for the answers. Nothing fancy here, my question node has a number attribute and a text attribute.  The answer nodes have a text attribute as well, and a value attribute to determine whether the radio button should be checked by default.</p>
<p>The XML looks like:</p>
<pre >&lt;?<span class="keyword">xml</span> <span class="class">version</span>="1.0" <span class="class">encoding</span>="iso-8859-1"?&gt;
&lt;<span class="keyword">questions</span>&gt;
    &lt;<span class="keyword">question</span> <span class="class">number</span>="1" <span class="class">text</span>="How painful is it to parse XML with JavaScript?"&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="Y" <span class="class">text</span>="Ungodly painful"&gt;&lt;/<span class="keyword">option</span>&gt;
       &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Extremely painful"&gt;&lt;/<span class="keyword">option</span>&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Moderately painful"&gt;&lt;/<span class="keyword">option</span>&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Mildly painful"&gt;&lt;/<span class="keyword">option</span>&gt;
    &lt;/<span class="keyword">question</span>&gt;
   &lt;<span class="keyword">question</span> <span class="class">number</span>="2" <span class="class">text</span>="How retarded is JScript?"&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Poo flinging retarded"&gt;&lt;/<span class="keyword">option</span>&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Extremely retarded"&gt;&lt;/<span class="keyword">option</span>&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="Y" <span class="class">text</span>="Moderately retarded"&gt;&lt;/<span class="keyword">option</span>&gt;
        &lt;<span class="keyword">option</span> <span class="class">value</span>="N" <span class="class">text</span>="Mildly retarded"&gt;&lt;/<span class="keyword">option</span>&gt;
    &lt;/<span class="keyword">question</span>&gt;
&lt;/<span class="keyword">questions</span>&gt;</pre>
<p>On to coding, you need to determine what sort of browser the user will be using to view your parsed XML.  The function I found to check the browser and load the XML appropriately, checks for Internet Explorer and non-evil-empire browsers, Firefox, Opera, etc.</p>
<p>Internet Explorer uses a different type of type of JavaScript when parsing a web page.  Without boring you about the details, the basic difference is Microsoft uses a custom version of JavaScript called JScript, leave it to Microsoft to make life hard on us all.</p>
<p>I gathered the load XML data function from <a href="http://www.w3schools.com/xml/xml_parser.asp">w3schools</a>.<br />
Here&#8217;s the function to check the browser and load the XML document:</p>
<pre ><span class="comments">//create variable to store the XML document</span>
<span class="keyword">var</span> xmlDoc;
<span class="comments">//set variable to a nodeType of ELEMENT_NODE</span>
<span class="comments">//this way we can easily tell what type of node we are grabbing in our code</span>
<span class="keyword">var</span> ELEMENT_NODE = 1;
<span class="comments">//create function to load the XML data from the specified document</span>
<span class="comments">//found this at w3schools http://www.w3schools.com/xml/xml_parser.asp</span>
<span class="keyword">function</span> loadXmlData()
{
    <span class="comments">// code for IE</span>
    <span class="keyword">if</span> (window.ActiveXObject)
    {
        <span class="comments">//setup active x object</span>
        xmlDoc=<span class="keyword">new</span> ActiveXObject(<span class="string">"Microsoft.XMLDOM"</span>);
        <span class="comments">//tell browser that its not an asynchronous call</span>
        xmlDoc.async=<span class="keyword">false</span>;
        <span class="comments">//provide URL to the XML document to be parsed</span>
        xmlDoc.load(<span class="string">"http://sbiefeld.com/wp-content/uploads/2008/03/questions.xml"</span>);
        <span class="comments">//call function to parse data</span>
        writeListForPOSBrowsers();
    }
    <span class="comments">// code for Mozilla, Firefox, Opera, etc.</span>
    <span class="keyword">else</span> <span class="keyword">if</span> (document.implementation &amp;&amp; document.implementation.createDocument)
    {
        <span class="comments">//set up document variable</span>
        xmlDoc = document.implementation.createDocument(<span class="string">""</span>, <span class="string">""</span>, <span class="keyword">null</span>);
        <span class="comments">//call function to parse data</span>
        xmlDoc.onload = writeListForRealBrowsers;
        <span class="comments">//provide URL to the XML document to be parsed</span>
        xmlDoc.load(<span class="string">"http://sbiefeld.com/wp-content/uploads/2008/03/questions.xml"</span>);
    }
    <span class="keyword">else</span>
    {
        <span class="comments">//fire alert if XML cannot be parsed by an unknown browser</span>
        alert(<span class="string">'Your browser cannot handle this script'</span>);
    }
}</pre>
<p>Notice the different function calls per browser, writeListForPOSBrowsers() and writeListForRealBrowsers(). This was to handle the peculiarities of IE and JScript.  The writeListForPOSBrowsers() function handles the parsing for IE while the writeListForRealBrowsers() function handles the parsing for other browsers.</p>
<p>I guess I will start with the writeListForPOSBrowsers() first and save the best for last. The basic flow is: loop through the question nodes in the XML file and pull out question attributes and parse them into HTML elements.  For each question node, I loop through the answer nodes to and create the radio buttons for the answer choices.</p>
<p>The most frustrating thing is the lack of support for the DOM that JScript has.  Instead of being able to reference HTML elements and append data accordingly I had to manually put my HTML elements in a string and then append to that string.  Once everything is in place, I put that HTML string in the document. See comments in code for more specifics.</p>
<pre ><span class="comments">//parses XML for IE browser</span>
<span class="comments">//because of lack of sufficient DOM support in JScript things are done a bit differently</span>
<span class="comments">//i.e. hard coding html elements</span>
function writeListForPOSBrowsers()
{
    <span class="comments">//searches for and gets the question tag elements in the XML file</span>
    var questions = xmlDoc.getElementsByTagName(<span class="string">'question'</span>);
    <span class="comments">//creates an HTML string and adds an unordered list element</span>
    var htmlCode = <span class="string">'&lt;ul&gt;'</span>;
    <span class="comments">//loop through all of the question elements</span>
    <span class="keyword">for</span> (i=0; i &lt; questions.length; i++)
    {
        <span class="comments">//get the question number from the number attribute of the question element</span>
        var questionId = questions[i].getAttribute(<span class="string">'number'</span>);
        <span class="comments">//add list item and question number to HTML string</span>
        htmlCode += <span class="string">'&lt;li&gt;'</span>+<span class="string">'('</span> + questionId + <span class="string">') '</span>;
        <span class="comments">//ensure we are still dealing with a node of type ELEMENT_NODE</span>
        <span class="keyword">if</span> (questions[i].nodeType != ELEMENT_NODE) <span class="keyword">continue</span>;
        <span class="comments">//store the question data</span>
        var cdata = questions[i].getAttribute(<span class="string">'text'</span>);
        <span class="comments">//add question data and closing list item tag to HTML string</span>
        htmlCode +=    cdata + <span class="string">'&lt;/li&gt;'</span>;
        <span class="comments">//time to loop through the answer nodes</span>
        <span class="keyword">for</span> (j=0; j &lt; questions[i].childNodes.length; j++)
        {
            <span class="comments">//adds break if not the first item, used purely for aesthetic reasons</span>
            <span class="keyword">if</span>(j!=0){htmlCode += <span class="string">'&lt;br/&gt;'</span>;}
            <span class="comments">//create a unique id for the input element</span>
            var inputId =  questionId + <span class="string">'_'</span> + j;
            <span class="comments">//ensure we are still dealing with a node of type ELEMENT_NODE</span>
            <span class="keyword">if</span> (questions[i].childNodes[j].nodeType != ELEMENT_NODE) <span class="keyword">continue</span>;
            <span class="comments">//gets any answer text data from the node</span>
            var rbtnTxt = questions[i].childNodes[j].getAttribute(<span class="string">'text'</span>);
            <span class="comments">//gets any value data from the node</span>
            var isChkd = questions[i].childNodes[j].getAttribute(<span class="string">'value'</span>);
            <span class="comments">//declare variable to hold isChecked value</span>
            var isChkdValue;
            <span class="comments">//checks value data to set checked attribute on radio button</span>
            <span class="keyword">if</span>(isChkd.toUpperCase() == <span class="string">'Y'</span>)
            {
                <span class="comments">//set radio button to checked</span>
                isChkdValue = <span class="string">'checked'</span>;
            }
            <span class="keyword">else</span>
            {
                <span class="comments">//set radio button to unchecked</span>
                isChkdValue = <span class="string">''</span>;
            }
            <span class="comments">//adds input element tags and attribute values to the HTML string</span>
            htmlCode += <span class="string">'&lt;input type="radio" id="'</span> + inputId + <span class="string">'" name="question'</span>+i+<span class="string">'" '</span>+isChkdValue+<span class="string">' value="'</span>+ rbtnTxt+<span class="string">'"'</span>;
            <span class="comments">//adds label element that stores answer text data to the HTML string</span>
            htmlCode += <span class="string">'&lt;label&gt;'</span>+rbtnTxt+<span class="string">'&lt;/label&gt;'</span>;
        }
        <span class="comments">//add break elements to the HTML string</span>
        htmlCode += <span class="string">'&lt;br/&gt;&lt;br/&gt;'</span>;
    }
    <span class="comments">//add questions and answers to the page</span>
    document.getElementById(<span class="string">'updateTarget'</span>).innerHTML = htmlCode;
}</pre>
<p>Now, the best for last. The function to parse XML for non-IE browsers.  In this function I could use the DOM, w00t for strongly typed objects, well kind of, since JavaScript is inherently not typed at all, but that is another topic.</p>
<p>I use exactly the same process as before loop through the question nodes and for each loop though its answer nodes.  Then append the parsed items to the page.</p>
<pre ><span class="comments">//parses XML for non-IE browsers</span>
<span class="keyword">function</span> writeListForRealBrowsers()
{
    <span class="comments">//searches for and gets the question tag elements in the XML file</span>
    <span class="keyword">var</span> questions = xmlDoc.getElementsByTagName(<span class="string">'question'</span>);
    <span class="comments">//creates an HTML ul element and stores it in a variable for later use</span>
    <span class="keyword">var</span> ul = document.createElement(<span class="string">'ul'</span>);
    <span class="comments">//loop through all of the question elements</span>
    <span class="keyword">for</span> (i=0; i &lt; questions.length; i++)
    {
        <span class="comments">//creates an new HTML li element and stores it in a variable</span>
        <span class="keyword">var</span> li = document.createElement(<span class="string">'li'</span>);
        <span class="comments">//creates an new HTML br element and stores it in a variable</span>
        <span class="keyword">var</span> brk = document.createElement(<span class="string">'br'</span>);
        <span class="comments">//get the question number from the number attribute of the question element</span>
        <span class="keyword">var</span> questionId = questions[i].getAttribute(<span class="string">'number'</span>);
        <span class="comments">//I create a text node to store the question number</span>
        <span class="keyword">var</span> questoinNum = document.createTextNode(<span class="string">'('</span> + questionId + <span class="string">') '</span>);
        <span class="comments">//append the question number to the list item element</span>
        li.appendChild(questoinNum);
        <span class="comments">//append the list item to the unordered list element</span>
        ul.appendChild(li);
        <span class="comments">//ensure that the current node we are looking at in the loop is an ELEMENT_NODE, if so continue on our journey</span>
        <span class="keyword">if</span> (questions[i].nodeType != ELEMENT_NODE) <span class="keyword">continue</span>;
        <span class="comments">//create a text node the hold the question data</span>
        <span class="keyword">var</span> cdata = document.createTextNode(questions[i].getAttribute(<span class="string">'text'</span>));
        <span class="comments">//append question data to the list item</span>
        li.appendChild(cdata);
        <span class="comments">//append a break element to the list item</span>
        li.appendChild(brk);
        <span class="comments">//time to loop through the answer nodes</span>
        <span class="keyword">for</span> (j=0; j &lt; questions[i].childNodes.length; j++)
        {
            <span class="comments">//creates an new HTML br element and stores it in a variable</span>
            <span class="keyword">var</span> brk = document.createElement(<span class="string">'br'</span>);
            <span class="comments">//create a input element for the current answer node we are on</span>
            <span class="keyword">var</span> inpt = document.createElement(<span class="string">'input'</span>);
            <span class="comments">//create a label to hold the answer data</span>
            <span class="keyword">var</span> lbl = document.createElement(<span class="string">'label'</span>);
            <span class="comments">//specify the type of input element, in this case a radio button</span>
            inpt.type = <span class="string">'radio'</span>;
            <span class="comments">//create a unique id for the input element</span>
            <span class="keyword">var</span> inputId =  questionId + <span class="string">'_'</span> + j;
            <span class="comments">//set the unique id</span>
            inpt.id = inputId;
            <span class="comments">//create a unique name for the input element</span>
            inpt.name = <span class="string">'question'</span> + i;
            <span class="comments">//ensure we are still dealing with a node of type ELEMENT_NODE</span>
            <span class="keyword">if</span> (questions[i].childNodes[j].nodeType != ELEMENT_NODE) <span class="keyword">continue</span>;
            <span class="comments">//gets any answer text data from the node</span>
            <span class="keyword">var</span> rbtnTxt = questions[i].childNodes[j].getAttribute(<span class="string">'text'</span>);
            <span class="comments">//gets any value data from the node</span>
            <span class="keyword">var</span> isChkd = questions[i].childNodes[j].getAttribute(<span class="string">'value'</span>);
            <span class="comments">//checks value data to set checked attribute on radio button</span>
            inpt.<span class="keyword">checked</span> = (isChkd.toUpperCase() == <span class="string">'Y'</span>);
            <span class="comments">//sets value data</span>
            inpt.value = rbtnTxt;
            <span class="comments">//appends answer text data to list item</span>
            lbl.appendChild(document.createTextNode(rbtnTxt));
            <span class="comments">//appends input element to list item</span>
            li.appendChild(inpt);
            <span class="comments">//appends answer text to the list item</span>
            li.appendChild(lbl);
            <span class="comments">//appends a break element to the list item</span>
            li.appendChild(brk);
        }
    }
    <span class="comments">//appends unordered list to the page</span>
    document.getElementById(<span class="string">'updateTarget'</span>).appendChild(ul);
}</pre>
<p>Last but not least, the HTML to use the javascript:</p>
<pre >&lt;<span class="keyword">body</span> <span class="class">onLoad</span>="loadXmlData()" <span class="class">id</span>='updateTarget'&gt;&lt;/<span class="keyword">body</span>&gt;</pre>
<p>Simple enough, right?  Well I hope my gatherings of how to parse XML with Javascript has been useful and helpful.  This may by no means be the best way to do it, and it could be re-factored.  It does however stay true to the title, Quick and Dirty XML Parsing with JavaScript.  Grab the <a href="http://sbiefeld.com/wp-content/uploads/2008/03/questions.xml">XML file</a> and grab and test the <a href="http://sbiefeld.com/wp-content/uploads/2008/03/questions.html">HTML/JavaScript</a>.  Thanks much and expect more.</p>
]]></content:encoded>
			<wfw:commentRss>http://sbiefeld.com/2008/03/quick-and-dirty-xml-parsing-with-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

