Online Exam Using XML & ASP

Introduction

This article assumes that you are familiar with ASP, XML and HTML.

Using this OnLine Exam system, we can conduct any type of objective type examinations on line. Eventhough I implemented most of the conventional things, the reader is highly appreciated to incorporate all other features whatever so.

Let us talk on the overall functionality. The Questions are in the xml file stored in the server (it could be in the database). When the user is ready to take the exam, then the question ids list for this user will be sent to the browser from the server via Microsoft’s XMLHTTP Object. Using this same XMLHTTP Object, the question contents are retrieved from the server and displayed on the page whenever the user requests for a question. On user’s response to any question, the selected answer is stored in the client side itself. On end of the exam, the result will be displayed. The duration and no of questions per exam are set as 5 minutes and 5 questions respectively. But we can set them to any possible values.

How it works

The following screens are identical to the OnLine Exam system:

 

OnLine Exam
The duration of this exam is 5 minutes. There is no order to answer a question. You may use Next as well as Previous button to get a question to answer.

 

OnLine Exam
Time: 13 min: 43 sec
Question: 3 of 5

What does KB stand for

Kilo Bits
Key Board
Kilo Bytes
None
 
The duration of this exam is 5 minutes. There is no order to answer a question. You may use Next as well as Previous button to get a question to answer.

 

Once user starts the exam, the question ids list will come from the server. For every request to the server for a question, a question id in the ids list stored in the client is fetched and sent to the server. The server will return the question content, corresponding to the question id, from the xml file.

When the user selects any one answer the system will store in the answers list as well as in the selection list in the client side. Answer list is used to check no of right answers the user has selected at the end. Selection list is there so that the system will automatically select the choice which the user has already selected (for example if the user clicks the Previous button)

The exam will be over either the user clicks the Finish button or the time is over (for example 5 minutes) which comes first. On finish, the system will calculate no of right answers and display it.

The following files are used in the OnLine Exam system:

OLExam.html

<html>
<script>
  var objXmlHTTP,objXmlDOM;
  var aQuest; //to store question ids
  var aAnswer = new Array(); // to track the result
  var aSelected = new Array(); // to store user's response
  var count = 0; //to store the current question no
  var ansSel = 0; //to store user's selection
  var ExamDuration = 5 * 60 ; // 5 minutes
  var timerID; //to store the setInterval fun's id
  var radIndex = -1; //to store the selected radio's index

  //constructor like function
  //here XML objects are created and
  //No of questions as well as question ids list
  //are fetched from the server.
  function init(){
    objXmlHTTP = new ActiveXObject("Microsoft.XMLHTTP");
    objXmlDOM = new ActiveXObject("Microsoft.XMLDOM");
    objXmlHTTP.open("POST","OLExam.asp?Action=Start",false);
    objXmlHTTP.send("");
    temp =objXmlHTTP.ResponseText;
    aQuest = temp.split(",");

    //initialize the user's answers list
    for(i=0;i<aQuest.length; i++){
      aAnswer[i] = 0; // 0 for wrong; 1 for right answer
      aSelected[i] = -1; // to store the radio's index
    }

    if(count < aQuest.length) {
      url = "OLExam.asp?Action=NextQ&QNo=" + aQuest[count];
      objXmlHTTP.open("POST", url ,false);
      objXmlHTTP.send("");
      objXmlDOM.loadXML(objXmlHTTP.ResponseText);
      
      //parse the response content fetched from the server
      //and display the question
      parseQ();
    }
    
    //change the Start button's caption and its click event
    document.frm.btnFinish.value = "Finish the Exam";
    document.frm.btnFinish.onclick = showResult; //function
    
    //start the timer
    timerID = setInterval("timer()",1000);
  }

  function getPreQ() {
    //update the user's answers list
    checkAnswer();
    
    //decrement the question no - i.e. to previous Question
    count--;
    
    //stop the timer
    clearInterval(timerID);
    
    //fetch the question for the aQuest[count] id
    url = "OLExam.asp?Action=NextQ&QNo=" + aQuest[count];
    objXmlHTTP.open("POST",url ,false);
    objXmlHTTP.send("");
    objXmlDOM.loadXML(objXmlHTTP.ResponseText);

    //parse the response content fetched from the server
    //and display the question
    parseQ();
    
    //start the timer
    timerID = setInterval("timer()",1000);
  }

  function getNextQ() {
    //update the user's answers list
    checkAnswer();

    //increment the question no - i.e. to next Question
    count++;

    //stop the timer
    clearInterval(timerID);

    url = "OLExam.asp?Action=NextQ&QNo=" + aQuest[count];
    objXmlHTTP.open("POST", url ,false);
    objXmlHTTP.send("");
    objXmlDOM.loadXML(objXmlHTTP.ResponseText);

    //parse the response content fetched from the server
    //and display the question
    parseQ();

    //start the timer
    timerID = setInterval("timer()",1000);
  }

  function parseQ(){
    //fetch the question from theXML Object
    //format the display 	
    strOut  = "<table border=0 align=center width=80%>";
    strOut += "<tr><td colspan=2><b>";
    strOut += "Question No: " + (count+1) + " of ";
    strOut += aQuest.length + "</b></td></tr>";
    strOut += "<tr><td colspan=2>&nbsp;</td></tr>";

    temp = objXmlDOM.selectSingleNode("data/qtext").text;

    strOut += "<tr><td colspan=2><b>"+temp+"</b></td></tr>";
    strOut += "<tr><td colspan=2>&nbsp;</td></tr>";

    Nodes = objXmlDOM.selectNodes("data/choice");

    for(i=0;i<Nodes.length;i++){
      strOut += "<tr><td align=center width=10%>";
      strOut += "<input type=radio name=ansUsr ";
      strOut += " onClick='ansSel=" + (i+1);
      strOut += ";radIndex=" + i + "' ";
      strOut += "value=" + (i+1) + "></td><td>";
      strOut +=  Nodes.item(i).text + "</td></tr>";		
    }

    //set ansNo (hidden field) to the actual answer
    temp = objXmlDOM.selectSingleNode("data/answer").text;
    document.frm.ansNo.value = temp;

    strOut += "<tr><td colspan=2>&nbsp;</td></tr>";
    strOut += "<tr><td colspan=2>";

    if(count != 0 ){
      strOut += "<input type=button value=Previous ";
      strOut += " onClick='getPreQ()'> ";
    }

    if(count < aQuest.length-1){
      strOut += " <input type=button value=Next";
      strOut += " onClick='getNextQ()'>";			
    }

    strOut += "</td></tr></table>";

    //set the strOut content to <P> tag named QArea
    QArea.innerHTML = strOut;

    //set the default value to ansSel
    ansSel = 0;
    radIndex = -1;

    //check the radio if user has selected previously
    if (aSelected[count] != -1) {
      radIndex = aSelected[count];
      ansSel = radIndex + 1;
      document.frm.ansUsr[radIndex].checked = true;
    }
  }

  function checkAnswer(){
    //store the selected radio's index
    aSelected[count] = radIndex;

    //if the user selection matches the actual answer
    if (ansSel == document.frm.ansNo.value)
      aAnswer[count] = 1;
    else
      aAnswer[count] = 0;
  }

  function showResult() {
    rights = 0;

    //stop the timer
    clearInterval(timerID);

    //update the user's answers list
    checkAnswer();

    //count no of answers
    for(i=0;i<aAnswer.length;i++){
      if(aAnswer[i] == 1)
      rights++;
    }
    strRes = "<h2 align=center><br>";

    //if all the answers are correct then greet
    if(rights == aAnswer.length)
      strRes += "<br><br>Congratulations...!";

    strRes += "<br><br>your score is " + rights;
    strRes += " out of " + aAnswer.length + "</h2>";

    document.write(strRes);
  }

  var timeCount = 0;
  function timer(){
    timeCount++;  //increment the time by one second

    //to display the time in the status bar,
    // uncomment the next line
    //window.status = "..." + timeCount + " secs" ;

    //to display the time
    temp =  "Time:   " + parseInt(timeCount/60);
    temp += "  min : " + (timeCount%60) + " sec ";
    TBlock.innerText = temp;

    //if the time is up
    if (timeCount == ExamDuration) {
      alert("Sorry, time is up");
      showResult();
    }
  }
</script>

<body>
<h2 align=center><font color=green>OnLine Exam</font></h2>

<form name=frm >
<table border=1 width=95% bgcolor=DarkSeaGreen align=center>
<tr><td align=right><b id=TBlock></b></td></tr>
<tr><td>
<p id="QArea">
<center>
<br>
Relax...! The duration of this exam is 5 minutes.
<br>
There is no order to answer a question. You may use Next as
well as Previous button to get a question to answer.
<br>
<br>
<input type=button name=btnFinish value="Start the Exam"
onClick="init()">
</center>
</p>
<input type=hidden name=ansNo>
</td></tr></table>
</form>

</body>
</html>

 

OLExam.asp

<%

Response.expires = 0
'create an instance of MS XMLDOM Object
'and load the QBank.xml file where all the questions are.

set obj = server.createobject("Microsoft.XMLDOM")
obj.async = false
obj.load(Server.MapPath("QBank.xml"))

'very first request from the client
if trim(request("Action")) = "Start" then
  'set no of questions per exam
  Dim NoQ,TotalQ
  
  NoQ = 5 'set no less than the totalquestions
  
  'count no of questions in the xml file
  '( or from database)
  TotalQ = obj.selectNodes("data/question").length

  Dim aQuest(),temp,isExist, strQ
  ReDim aQuest(0) 'to store the question ids
  
  'generate (=NoQ) question ids randomly
  while ubound(aQuest) < NoQ
    isExist = false
    temp = Int((TotalQ * Rnd) + 1)
    for i = 1 to ubound(aQuest)
      if aQuest(i) = temp then
        isExist = true
        exit for
      end if
    next
    if Not isExist then
      Redim Preserve aQuest(ubound(aQuest)+1)
      aQuest(ubound(aQuest)) = temp
      strQ = aQuest(i) & "," & strQ
    end if
  wend
  
  'remove the last comma ',' from strQ
  strQ = left(strQ,len(strQ)-1)
  
  'send the question in the strQ to the client
  response.write strQ
  
'all further requests - after the first request
elseif trim(request("Action")) = "NextQ" then
  'fetch the question from the XML Object
  'and form the output string
  temp = "data/question[@id=" & trim(request("QNo")) & "]"

  set Node = obj.selectSingleNode(temp)

  strXML = "<data>"
  strXML = strXML & "<qtext>"
  strXML = strXML & Node.selectSingleNode("qtext").text
  strXML = strXML & "</qtext>"
  strXML = strXML & "<answer>"
  strXML = strXML & Node.selectSingleNode("answer").text
  strXML = strXML & "</answer>"

  set Node = Node.selectNodes("choices/choice")

  for i = 0 to Node.length-1
    strXML = strXML & "<choice>"
    strXML = strXML & Node.item(i).text
    strXML = strXML & "</choice>"
  next

  strXML = strXML & "</data>"

  'send the output to the client
  Response.Write (strXML)
end if
%>

 

QBank.xml

<?xml version="1.0"?>
<data>
  <question id="1">
    <qtext>What does KB stand for?</qtext>
    <choices>
      <choice>Kilo Bits</choice>
      <choice>Key Board</choice>
      <choice>Kilo Bytes</choice>
      <choice>None</choice>
    </choices>
    <answer>3</answer>
  </question>
  <question id="2">
    <qtext>CPU stands for</qtext>
    <choices>
      <choice>Central Processing Unit</choice>
      <choice>Central Power Unit</choice>
      <choice>Core Processing Unit</choice>
      <choice>Core Power Unit</choice>
    </choices>
    <answer>1</answer>
  </question>
  <question id="3">
    <qtext>1 KB equals</qtext>
    <choices>
      <choice>1000 Bytes</choice>
      <choice>1024 Bytes</choice>
      <choice>1000 Bits</choice>
      <choice>1024 Bits</choice>
      <choice>Nothing</choice>
    </choices>
    <answer>2</answer>
  </question>
  <question id="4">
    <qtext>RAM is </qtext>
    <choices>
      <choice>Random Access Modifier</choice>
      <choice>Primary Memory</choice>
      <choice>Secondary Memory</choice>
      <choice>Read And Modify</choice>
    </choices>
    <answer>2</answer>
  </question>
  <question id="5">
    <qtext>Hard Disk is </qtext>
    <choices>
      <choice>Hard to break</choice>
      <choice>Primary Memory Storage</choice>
      <choice>Temporary Memory Storage</choice>
      <choice>Secondary Memory Storage</choice>
    </choices>
    <answer>4</answer>
  </question>
  <question id="6">
    <qtext>Computer Monitor is used </qtext>
    <choices>
      <choice>To monitor activities</choice>
      <choice>To control Computer</choice>
      <choice>As display unit</choice>
      <choice>None</choice>
    </choices>
    <answer>3</answer>
  </question>
  <question id="7">
    <qtext>XML stands for</qtext>
    <choices>
      <choice>Extended Markup Language</choice>
      <choice>Extended Model Language</choice>
      <choice>Extensible Markup Language</choice>
      <choice>Extensible Model Language</choice>
    </choices>
    <answer>3</answer>
  </question>
  <question id="8">
    <qtext>ASP stands for</qtext>
    <choices>
      <choice>Active Server Page</choice>
      <choice>Application Service Provision</choice>
      <choice>As Soon as Possible</choice>
      <choice>All</choice>
    </choices>
    <answer>1</answer>
  </question>
</data>

Related posts

SOAP Soup

Introduction Simple Object Access Protocol is one of the neatest XML based technologies to be introduced as of late, yet many people are still trying to get a handle on all of the new terms and acronyms that SOAP has uncovered. This article is written to help you dig through the SOAP...

Read More

Using XML to build an ASP+ config.web Editor

Introduction ASP+ configuration information is stored in XML-based configuration files. Using built-in features of IIS 5.0 and IE 5.0 such as the FileSystemObject, the XML Document Object Model (DOM) and XML Data Islands, we can easily develop a rich tool for modifying and editing these configuration files. In this...

Read More

Saving HTML Form Data to XML

Introduction This example assumes that you are familiar with ASP, XML and HTML 4.0. Storing your form submissions in XML Usually form submissions in ASP are written to some sort of database management system. However, if you need your form submission data to be more portable, it can be...

Read More