創(chuàng)建在線測試的思想來自于我尋找XML的輔導(dǎo)課程的一次偶然機會。我訪問了W3School.com網(wǎng)站發(fā)現(xiàn)更令人感興趣是這個網(wǎng)站里的一個在線測試而不僅僅是尋找XML的輔導(dǎo)課程。我一次做了20道測試題感覺相當好。我不知道為什么只有一些網(wǎng)頁提供了這種在線測試的服務(wù)。
測試是一個很好的考察知識的方法。一個在線測試是對一個網(wǎng)頁來說是一個很好的補充,他可以讓訪問者停留在網(wǎng)頁上更長的時間。
下載了試用版本并用了一下,是一個加強你對澳大利亞地理知識的十道測驗。他的答案是寫在一個透明的普通人都可以看得懂的XML文檔,我們可以很容易看到答案。
代碼解釋
我不會詳細解釋代碼的每個細節(jié),而重點討論其中某些部分。一旦明白代碼的整體意義,就可以修改或增加代碼以滿足個人需求。
遞歸代碼
在這個在線測試的網(wǎng)頁里只有一個活動的遞歸代碼完成多項不同的任務(wù),遞歸代碼就是一種可以反復(fù)調(diào)用自己本身直到定義的條件達到為止。準確的說這種代碼并沒有調(diào)用自身,只是傳遞形成的數(shù)據(jù)給自身,這個過程被稱為往回傳遞。
由于這種代碼在測試期間不斷的往回傳遞信息給自身,可以說這種代碼有多種狀態(tài)。第一個狀態(tài)是初始化一些基本變量,計算總的問題數(shù)和記錄測試的開始時間。然后,在第一個和以后的各個狀態(tài)里該代碼讓頁面上顯示出一道多項選擇題讓用戶回答(可以參看上面的圖片)?;卮饐栴}后會觸發(fā)一個onClick事件促使往回傳遞,并推動代碼運行到下一個狀態(tài)。在這個狀態(tài)下代碼會在事件發(fā)生的同時運行一個子程序來檢查答案并顯示下一道問題。遞歸不斷重復(fù)直到最后一個問題回答完畢,頁面顯示出答題結(jié)果的時候。
下面的工作圖表可以表示出這種在線測試的遞歸流的代碼的運行過程:

狀態(tài)維護
在線測試的代碼需要維護它各個變量的狀態(tài)。有許多可供選擇的辦法來解決,最先進的方法是使用session對象而最傳統(tǒng)的方法是使用輸入隱藏或者使用一種QueryString。ASP.NET引入了一種叫做‘state bag’的方法。與session對象不同的是‘state bag’不是一直檢測整個用戶會話過程而是象隱藏輸入和QueryString一樣提前到從一頁到另一頁轉(zhuǎn)換的時候。然而它又比隱藏輸入和QueryString高級,這是因為它可以接受更多的數(shù)據(jù)類型以及它的內(nèi)容被編譯成一個單獨的字符串從而不容易被任意更改。
存儲數(shù)值到‘state bag’
ViewState("TotalQuestion") = intTotalQuestion
從‘state bag’中取值
intTotalQuestion = ViewState("TotalQuestion")
下面的表格是變量存儲在‘state bag’中的清單
變量名 | State Bag 名 | 數(shù)據(jù)類型 | 說明 |
intTotalQuestion | TotalQuestion | int | 在測試中保存總問題數(shù)。它的值在初始狀態(tài)的時候賦予并保存為恒量。 |
intScore | Score | int | 保存答對的問題數(shù) |
intQuestionNo | QuestionNo | int | 保存目前用戶回答的最后一個問題的題號 |
arrAnswerHistory | AnswerHistory | arraylist of int | 記錄測試的答案。如果回答正確記0否則記錄所選擇的答案的索引號。 |
(none) | CorrectAnswer | int | 保存上一問題的正確答案。當答案被檢查正確是下一狀態(tài)可用。 |
(none) | StartTime | date | 保存測試的開始時間,可以用來計算測試所耗費的時間。 |
XML數(shù)據(jù)
在線測試的數(shù)據(jù)保存在叫做quiz.xml的可以使用XML表quiz.xsd的XML的文檔里。一個有效的XML文檔含有一個叫quiz的元素集合里,它至少有一個叫mchoice的元素(multiple-choice的簡寫)。每個mchoice元素有一個問題子元素和兩個以上的答案子元素。答案元素可能有correct屬性其值為yes或no。事實上,在一同個mchoice里要給每個答案一個correct屬性的yes值,否則這個問題就不會有正確答案。
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>
為XML數(shù)據(jù)插入HTML標簽是必要的,可以使頁面含有修飾過的文檔,圖片,鏈接等而不會只有單調(diào)的文檔。只要把CDATA塊圍繞在HTML標簽周圍就可以保證XML文檔的可用性??纯聪旅娴睦樱?/div>
quiz.xsd:
<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>
有以下幾個原因可以說明在線測試的代碼不會使XML文檔違背XML表。
第一、 它是一種強制資源進程,迫使XMLTextReader瀏覽文檔里的每個元素每個屬性。
第二、 我們不需要每次載入文件時激活XML文檔只要在更新以后激活一次就夠了,可以使用一個單獨的aspx代碼或者使用第三方工具并在每次XML文檔更新完后手動運行來激活XML文檔
XML文檔的對象模板
XML文檔的對象模板(DOM)是一個基于與其父結(jié)點和子結(jié)點繼承關(guān)系的表現(xiàn)每個XML文檔結(jié)點的樹狀結(jié)構(gòu)。XML文檔的對象模板允許通過多種邏輯途徑來操作XML文檔
我們使用XMLDocument類來建立XML文檔的對象模板。XMLDocument類是對XMLNode類的擴展,它可以從XMLNode類中繼承許多性質(zhì)和方法。當XMLNode類的性質(zhì)與方法在XML文檔的某個結(jié)點應(yīng)用的時候,XMLDocument類的性質(zhì)與方法就在整個XML文檔中應(yīng)用。
下面的代碼是從quiz.xml建立XMLDocument類的實例和XML文檔的對象模板
Dim xDoc as XMLDocument = New XMLDocument()
xDoc.Load(Server.MapPath("quiz.xml"))
在XML文檔的對象模板中定位一個具體的結(jié)點有一點技巧。我們要讓指針‘pointer’從根結(jié)點通過XML文檔的對象模板的起點。下面的代碼表明如何定位第一個問題和第一個多選項:
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)
很明顯是一個單調(diào)乏味的工作,尤其是當你想定位到一個處于低層次的結(jié)點的時候。幸運的是我們可以利用XPath語言來更直接定位一個具體結(jié)點或者一組結(jié)點。如果你多XPath不熟悉,可以參看下一段對它的簡單介紹。
XMLNode 和 XMLDocument類的 SelectNodes方法接受一個XPath字符串并返回一組叫做XMLNodeList的XMLNode的對象。另一種方法叫做SelectSingleNode作同樣的事情但只返回一個XMLNode對象
‘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是一種在XML文檔中定位具體結(jié)點的語言。它通過一個描述繼承關(guān)系的字符串來定位一個結(jié)點或一組結(jié)點,因此這種字符串通常被稱為XPath字符串。如果你對文件路徑或URL熟悉的話那么XPath的概念并不是新東西。
從XPath字符串的左邊讀到右邊你就可以指出它所定位的結(jié)點。除了一些情況或用途,XPath都很好用。下面的表格是XPath依靠quiz.xml的一些使用:
XPath字符串 | 結(jié)果 |
/quiz | 選擇包含所有元素的XML根結(jié)點 |
/quiz/mchoice | 選擇quiz的所有mchoice子元素 |
/quiz/mchoice[1] | 選擇quiz的第一個mchoice的子元素 |
/quiz/mchoice[1]/question | 選擇quiz的第一個mchoice的所有問題 |
/quiz/mchoice[1]/answer[4] | 選擇quiz 的第一個mchoice的第四個答案 |
/quiz/mchoice[1]/answer[4]/@correct | 選擇quiz的第一個mchoice的第四個答案的‘correct’屬性 |
XPath包含太多的驚奇。如果你有興趣了解更多的話,可以在W3CSchools中找到XPath的輔導(dǎo)課程。
總結(jié)
這篇文章介紹了在線測試作為一種工具對你的網(wǎng)頁來說是很好的補充。它也闡述了一些主題象遞歸代碼,使用在XML文檔的對象模板來操作和控制XML文檔,稍微提到XPath語言,并簡單討論了狀態(tài)維護。評論:
# re: 使用XML的DOM和XPath來創(chuàng)建多項選擇題的在線測試 2005-06-23 10:17 | YuL
文章沒完全看懂,但在看的過程中想到一個小小的問題,就是這里是如何對付[后退]的囁???我是一個很不小心的參與者,當我點了[NEXT]才發(fā)現(xiàn)好象自己應(yīng)該選另外一個答案,那我只好點[后退]再填,那么這時VIEWSTATE里的東東是回到以前的狀態(tài)囁,還是已經(jīng)到了新的狀態(tài)?然后就是當我又一次點[NEXT]后,突然又改變主意,想改前面某一題的選擇,我又不斷的點[后退],結(jié)果哦哦哦~~~~暈倒!HOW TO? 回復(fù)
# re: 使用XML的DOM和XPath來創(chuàng)建多項選擇題的在線測試 2005-06-28 15:17 | .Net Swimmer
re: 使用XML的DOM和XPath來創(chuàng)建多項選擇題的在線測試 2005-06-23 10:17 | YuL
文章沒完全看懂,但在看的過程中想到一個小小的問題,就是這里是如何對付[后退]的囁???我是一個很不小心的參與者,當我點了[NEXT]才發(fā)現(xiàn)好象自己應(yīng)該選另外一個答案,那我只好點[后退]再填,那么這時VIEWSTATE里的東東是回到以前的狀態(tài)囁,還是已經(jīng)到了新的狀態(tài)?然后就是當我又一次點 [NEXT]后,突然又改變主意,想改前面某一題的選擇,我又不斷的點[后退],結(jié)果哦哦哦~~~~暈倒!HOW TO?
呵呵,這些好像不是本文考慮的問題。在具體實現(xiàn)過程中,這的確應(yīng)該好好解決。感謝 回復(fù)
文章沒完全看懂,但在看的過程中想到一個小小的問題,就是這里是如何對付[后退]的囁???我是一個很不小心的參與者,當我點了[NEXT]才發(fā)現(xiàn)好象自己應(yīng)該選另外一個答案,那我只好點[后退]再填,那么這時VIEWSTATE里的東東是回到以前的狀態(tài)囁,還是已經(jīng)到了新的狀態(tài)?然后就是當我又一次點 [NEXT]后,突然又改變主意,想改前面某一題的選擇,我又不斷的點[后退],結(jié)果哦哦哦~~~~暈倒!HOW TO?
呵呵,這些好像不是本文考慮的問題。在具體實現(xiàn)過程中,這的確應(yīng)該好好解決。感謝 回復(fù)