程序人生

一头犁牛半块田,收也凭天,荒也凭天;粗茶淡饭饱三餐,早也香甜,晚也香甜;布衣得暖胜丝棉,长也可穿,短也可穿;草舍茅屋有几间,行也安然,住也安然;雨过天晴驾一船,鱼在一边,酒在一边;夜归儿女话灯前,今也有言,古也有言;日上三竿我独眠,谁是神仙,我是神仙

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Sample Image - xmlquiz_snapshot.gif

Introduction

The idea to write an online quiz came up when I was looking for an XML tutorial. I visited W3Schools.com and found not only the tutorial I was looking for, but more interestingly was an online quiz. I took the 20-questions quiz once, and hey! I felt great about it. I wonder why there are just few web sites offering online quiz like that.

A quiz is a great way to test your knowledge. An online quiz is a great addition to your web site that could keep your visitors glued for a few more minutes.

Download the demo project and try it. It is a 10-question quiz to challenge your knowledge about Australian geography. Don't worry! All data is kept in a clear, human-readable XML document, so you could easily peek for answers.

The Script Explained

I will not go through a very detail discussion about the script, but rather highlight several areas in the script. Once you get the whole idea about the script, then it is easy to modify or extend the script to suit your requirements.

Recursive Script

There is only one aspx script to do various tasks in the online quiz. It is a recursive script: a script that 'calls' itself over and over again until a certain condition is reached. Precisely, the script does not call itself, but posts form data to itself. This process is known as post back.

As the script posts back to itself continuously over the duration of the quiz, we could say that it has many states. The first state is to initialize several essential variables, count the total question, and record the quiz start time. Then, in the first and each following state, the script displays a multiple choice question to challenge user (see the snapshot above). A user answering the question will trigger onClick event, forcing a post-back, and move the script to the next state. In the next state, the script will run a subroutine associated with the event to check the answer and display the next multiple question. The recursive flow repeats again and again, until the last question is processed, where at this point a result is displayed.

The following activity diagram represents the recursive flow of the online quiz script. 

Maintaining State

The online quiz script needs to maintain state of its variables. There are a bunch of alternatives to do so. The most advanced way is to use the session object, and the conventional way is to use hidden inputs or a QueryString. ASP.NET introduces another alternative called 'state bag'. Unlike the session object, state bag is not persisted over the whole user session, but is brought forward from one page to another page just like hidden inputs and querystring. However, it is superior to hidden inputs and QueryStrings, since it can accept more data types and the content has been encoded into a single string and therefore is not easy to tamper with.

Storing value into state bag:

ViewState("TotalQuestion") = intTotalQuestion

Getting value from state bag:

intTotalQuestion = ViewState("TotalQuestion")

The following is a list of variables to be kept in the state bag:

Variable Name State Bag Name Data Type Comments
intTotalQuestion TotalQuestion int Keeps the total question in the quiz. The value is populated in the first state of the quiz and remains constants over the duration of quiz.
intScore Score int Keeps the number of correct answer.
intQuestionNo QuestionNo int Holds the last question number the user attempted.
arrAnswerHistory AnswerHistory arraylist of int Records answers in the quiz. It will record 0 (zero) if the answer is correct, otherwise record the selectedindex of the radio buttons.
(none) CorrectAnswer int Holds the correct answer of previous question. It is made available in the next state when the answer is checked for correctness.
(none) StartTime date Holds the start time of the quiz. It is used to calculate the time spent in the quiz.

 

XML Data

Data for the online quiz is kept in an XML document named quiz.xml, which is validated using an XML schema named quiz.xsd. A valid XML document consists of a root element called quiz, which has at least one element called mchoice (short for multiple-choice). Each mchoice element has one question child element, and two or more answer child elements. The answer element may have the correct attribute with possible value of either yes or no. In fact, you should supply the correct attribute with a value of yes to one of the answers in the same mchoice, otherwise there will be no correct answer for the question.

quiz.xml:

<?xml version="1.0" encoding="UTF-8"?>
<quiz xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="quiz.xsd">
  <mchoice>
    <question>What is the capital city of Australia ?</question>
    <answer>Sydney</answer>
    <answer correct="yes">Canberra</answer>
    <answer>Melbourne</answer>
    <answer>Gold Coast</answer>
  </mchoice>
  <mchoice>
    <question>Which city has an extensive tram network?</question>
    <answer>Sydney</answer>
    <answer correct="yes">Melbourne</answer>
    <answer>Adelaide</answer>
    <answer>Ballarat</answer>
  </mchoice>
</quiz>

It is possible to insert HTML tags within the XML data, therefore the quiz may contain decorated texts, images, links, etc. instead of plain text. Just make sure to enclose the HTML tags with CDATA block, so the XML document is still valid. Look at the following example:

  <mchoice>
    <question><![CDATA[Which of the following is <u>NOT</u> 
Australian native animals?]]></question>
    <answer>Kangaroo</answer>
    <answer correct="yes">Penguin</answer>
    <answer>Koala</answer>
    <answer>Wombat</answer>
  </mchoice>

quiz.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="quiz">
    <xs:complexType>
      <xs:choice>
        <xs:element name="mchoice" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="question" type="xs:string"/>
              <xs:element name="answer" minOccurs="2" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:simpleContent>
                    <xs:extension base="xs:string">
                      <xs:attribute name="correct" use="optional">
                        <xs:simpleType>
                          <xs:restriction base="xs:string">
                            <xs:enumeration value="yes"/>
                            <xs:enumeration value="no"/>
                          </xs:restriction>
                        </xs:simpleType>
                      </xs:attribute>
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

The online quiz script does not validate the XML document against the XML Schema for several reasons. First, it is a resource intensive process, forcing XMLTextReader to go through each element and attribute in the XML document. Second, we need to validate the XML document just once after it has been updated, instead of every time we load the file. To validate the XML document, you could write a separate aspx script or use a third-party tool and run them manually every after you finish updating the XML document.


XML Document Object Model

XML Document Object Model (DOM) is a tree-like structure that represents every node of an XML document based on the hierarchical relationship with its parent nodes and child nodes. The DOM allows us to navigate and manipulate XML document in more logical way.

To build an XML DOM, we use the XMLDocument class. The XMLDocument class itself extends the XMLNode class, therefore many of its properties and methods are inherited from XMLNode. While XMLNode's methods and properties apply to a specific node in an XML document, methods and properties of XMLDocument apply to the whole XML document.

The following code create an instance of XMLDocument and build XML DOM from quiz.xml:

Dim xDoc as XMLDocument = New XMLDocument()
xDoc.Load(Server.MapPath("quiz.xml"))

Addressing a specific node in the XML DOM is a bit tricky. We should navigate our 'pointer' through the DOM starting from its root node. The following code demonstrates how to address the first question of the first multiple choice:

Dim xNode as XMLNode

'Goto the first/base element in the file, which is <?xml ?>
xNode = xDoc.DocumentElement

'Goto the next sibling of current node, which is <quiz>
xNode = xNode.NextSibling

'Goto the first child of current node, which is <mchoice>
xNode = xNode.FirstChild

'Goto the first child of current node, which is <quiz>
xNode = xNode.FirstChild

'Print the content of current node
Response.Write("The question is: " & xNode.InnerHtml)

It is definitely a tedious task, particularly if you want to address nodes located at a very low level in the hierarchy. Luckily, we can utilize the XPath language to more directly address a specific node or a group of nodes. If you are unfamiliar with XPath, it will be briefly explained in the next section.

The SelectNodes method of the XMLNode and XMLDocument class' accepts an XPath string and returns a collection of XMLNode objects, called XMLNodeList. Another method, SelectSingleNode, does just the same thing but return only a single XMLNode object.

'Using SelectNodes to address all answers of the first multiple choice
Dim xNodeList As XMLNodeList
Dim i as Integer
xNodeList = xDoc.SelectNodes("/quiz/mchoice[1]/answer")
For i = 0 to xNodeList.Count-1
  Response.Write("<p>" & xNodeList.Item(i).InnerHtml)
Next


'Using SelectSingleNode to select the first question of the first multiple choice
Dim xNode as XMLNode
xNode = xDoc.SelectSingleNode("/quiz/mchoice[1]/question")
Response.Write("The question is: " & xNode.InnerHtml)


XPath

XPath is a language to address specific nodes in an XML document. It could address a single node or a group of nodes by describing its hierarchy relationship in a string, therefore it is often called an XPath string. If you are familiar with file path or URL, then the concept of XPath is nothing new.

Read the XPath string from left to right and you will be able to figure out the node it is addressing. Except for several conditions and functions, XPath is actually easy to use. The following table demonstrates some usage of XPath against quiz.xml:

XPath String Result
/quiz Select the root node of XML including all elements it contains. 
/quiz/mchoice Select all mchoice child elements of the quiz
/quiz/mchoice[1] Select the first mchoice (multiple choice) child element of the quiz
/quiz/mchoice[1]/question Select all questions of the first multiple choice of the quiz
/quiz/mchoice[1]/answer[4] Select the fourth answer of the first multiple choice of the quiz
/quiz/mchoice[1]/answer[4]/@correct Select 'correct' attribute of the fourth answer of the first multiple choice of the quiz

XPath contains a lot more surprises. If you are interested enough to explore more, check out the XPath Tutorial at W3CSchools.

Conclusions

This article presented an online quiz as a tool to add interactivity to your web site. It also explored several topics like recursive scripts, navigating and manipulating XML documents using the XML DOM, a glimpse of the XPath language, and a brief discussion about state maintenance.

posted on 2004-09-06 21:31  啸天犬  阅读(914)  评论(0编辑  收藏  举报