如今,XML 中应用最广泛的评估、测试和独立问题标记标准就是 IMS 问题与测试交互 (QTI)。IMS 是一个与电子学习标准相关的组织(参考资料 部分提供了一个相关链接),致力于多种标准,范围从元数据到传输学员信息。QTI 使得在 XML 中标记问题、将问题排列为测试和评估、添加元数据以及将所有内容压缩为一个 ZIP 文件的方式得以标准化。
QTI XML 不仅描述问题、评估和测试的静态部分(文本、布局、顺序等),还能描述其动态行为:例如,在用户给出错误的答案时采取怎样的行动、何时提供某些反馈、如何计算分数等。您可以任意增加此过程的复杂度,QTI 将为您提供编程工具,帮助您实现一切。
遗憾的是,QTI 的工作方式有些难以理解。文档以定义 标准为主,而非做出解释。IMS 问题与测试交互实现指南(参考资料 部分提供了一个链接)是一份非常有用的文档,也提供了一些示例,但仍然未能提供有关 QTI 内幕的过多细节。
本文探讨了 QTI 基本构造模块(即评估题项)中的响应和结果处理。如何为用户的响应评分、如何利用它来实现评分?
如果您还不熟悉 QTI,这一节将简单介绍评估题项。
评估题项 (或者简称为题项)是 QTI 的基本构造模块。一个题项可以包含复杂度任意的文本(及标记)、多个不同类型的问题、侧面的信息面板、多媒体对象等内容的组合。 它还定义自己的结果和响应处理,在认为答案正确时评分并给出反馈。
在实践中,QTI 评估题项通常并不复杂。我见过的大多数题项仅包含一个问题。清单 1 给出了一个 QTI 评估题项的剖析。
清单 1. 一个 QTI 题项的剖析
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" ...> <responseDeclaration ...> <!-- Information about the answers to the questions inside --> </responseDeclaration> <outcomeDeclaration ...> <!-- Internal variables for computing scores, controlling feedback, etc. --> </outcomeDeclaration> <itemBody ...> <!-- Text and the interactive parts (questions) --> </itemBody> <responseProcessing ...> <!-- How to handle the user's response --> </responseProcessing> <modalFeedback ...> <!-- Optional feedback messages to the user --> </modalFeedback> </assessmentItem> |
下面给出了标记的详细分析:
-
一个
<responseDeclaration>包含有关一个问题的答案(响应)的信息:它在怎样的情况下是正确的,以及(可选的)应该如何为其评分?<itemBody>中的每一个独立问题都需要一个<responseDeclaration>。 -
<outcomeDeclaration>定义一个内部变量,例如,该变量用于将评分返回至环境,或者用于控制提供给用户的反馈。 -
单独一个
<itemBody>元素包含此题项的文本、标记和问题。标记与 XHTML 极为相似,但应该注意:尽管您会看到多种熟悉的元素,例如<p>和<ul>,但所有内容均处于 QTI 名称空间 (http://www.imsglobal.org/xsd/imsqti_v2p1) 之中,而非 处于 XHTML 名称空间之中。标准并未规定必须使用浏览器呈现,这为解释说明留出了充足的空间。因此,在不同的 QTI 处理引擎之间交换内容时,主要问题之一就是一致的呈现。 -
<responseProcessing>部分描述了在学员完成该题项时执行的操作。其内容是一种简单的编程语言,您可以在其中执行计算、设置<outcomeDeclaration>变量等。 -
最后,
<modalFeedback>定义了题项为学员提供的反馈(例如,在答案正确时显示 “太棒了”)。
本文主要介绍
<responseDeclaration>、<outcomeDeclaration> 和
<responseProcessing> 部分。
题项中的
<itemBody>
元素包含与用户之间的零项或多项交互。大多数此类交互都是典型的问题(例如,多选题、排序题、填空题)。您还可以添加其他交互,例如 “上传文档”、“绘制图片” 以及 “开始播放影片”。
清单 2 提供了一个多选题示例。
清单 2. 多选题交互示例
<itemBody>
<choiceInteraction responseIdentifier="RESPONSE" shuffle="true" maxChoices="1">
<prompt>What is the top color of the Dutch flag?</prompt>
<simpleChoice identifier="A">Red</simpleChoice>
<simpleChoice >="B">Orange</simpleChoice>
<simpleChoice identifier="C">Black</simpleChoice>
<simpleChoice identifier="D">White</simpleChoice>
</choiceInteraction>
</itemBody>
|
此外,清单 3 提供了一个排序题的示例。
清单 3. 排序题交互示例
<itemBody>
<orderInteraction responseIdentifier="RESPONSE" shuffle="false">
<prompt>Order these cities from north to south:</prompt>
<simpleChoice identifier="A">Tripoli</simpleChoice>
<simpleChoice identifier="B">Stockholm</simpleChoice>
<simpleChoice identifier="C">Paris</simpleChoice>
</orderInteraction>
</itemBody>
|
QTI v2.1 定义了 20 种交互类型。您可以在 IMS 问题与测试交互实现指南 中找到一组完整的示例。 您可以确定使用哪种类型,但请注意,并非所有 QTI 处理引擎均支持所有交互类型。
如本例所示,一个交互拥有一个
responseIdentifier
属性,它将此项交互性与拥有相同标识符的
<responseDeclaration>
绑定。这是结果和响应处理的链接,稍后我们再介绍相关内容。
要理解 QTI 的响应和结果处理,一个重要的先决条件就是理解其数据模型及其复杂度背后的缘由。
在用户完成一个 QTI 题项时,需要检查答案。为此,答案将显示为数据。有些时候,数据非常简单:一个有多个选项、但仅有惟一答案的问题只需返回给定答案的标识符即可,数值滑块交互返回一个数值。然而,大多数交互类型都要更为复杂。距离来说:
- 多选项、多答案问题,返回一组问题标识符(例如,“所检查的答案的标识符是 A、C 和 D。”)。
- 排序将返回答案标识符的有序集(例如,“所创建的序列的标识符是 C、A 和 B。”)。
- 将多个词彼此关联的问题将返回一组标识符对(例如,“词的关联关系是 (A, C)、(B, D) 和 (E, F)。”)。
- 将对象定位在一个地图中将返回一组点(例如,“对象放置的位置是 (102, 10), (125, 653)。”)。
要确定一个答案是否正确,方法就是利用与交互绑定的
<responseDeclaration>。这就意味着,它必须拥有针对该项交互的正确数据类型。例如,
清单 4
为 <positionObjectInteraction> 提供了一个声明,在这种问题类型中,您必须将对象定位在一个图片中(例如,一幅地图)。其数据类型是一组点。
清单 4. 使用一组点的响应声明
<responseDeclaration identifier="RESPONSE" baseType="point" cardinality="multiple">
<correctResponse>
<value>118 184</value>
<value>150 235</value>
<value>96 114</value>
</correctResponse>
</responseDeclaration>
|
QTI 数据类型是通过 <responseDeclaration>
和
<outcomeDeclaration> 元素的
baseType
和
cardinality
属性定义的:
-
baseType属性定义基本数据类型:-
boolean -
directedPair -
duration -
file -
float -
identifier -
integer -
pair -
point -
string -
uri
-
-
cardinality属性定义baseType元素的数量和集合是否有序。值为:-
multiple -
ordered -
record(一种特殊、较为复杂的类型,本文中未作讨论) -
single
-
响应和结果处理负责用户完成题项时的操作。QTI 处理器必须执行各种任务,例如确定答案是否正确、计算评分、提供反馈等。<responseDeclaration>、<outcomeDeclaration> 和
<responseProcessing>
部分在此过程中均承担着一定的责任。
<responseDeclaration> 元素的标识符始终将其绑定到题项主体内的一项交互。清单 5 给出了一个示例。
清单 5. 将一项交互绑定到其响应声明
<responseDeclaration identifier="QUESTION1" cardinality="single"
baseType="identifier">
<correctResponse>
<value>B</value>
</correctResponse>
</responseDeclaration>
<itemBody>
<choiceInteraction responseIdentifier="QUESTION1" shuffle="false" maxChoices="1">
<prompt>Is a goldfish a mammal?</prompt>
<simpleChoice identifier="A">Yes</simpleChoice>
<simpleChoice identifier="B">No</simpleChoice>
</choiceInteraction>
</itemBody>
|
<responseDeclaration>
并非简单的变量:最好将其视为面向对象意义上的一个对象。此对象有三个 “方法”,您可以在题项的
<responseProcessing>
部分的计算中利用这些方法:
- 获取学员对问题的响应。
- 获取问题的正确(最优)响应。
- 根据不同的得分点对应不同的答案,允许答案存在细微差别,而非以简单的正确或错误论断。
清单 6
提供了一个
<responseDeclaration> 示例,其中根据给定的答案计算出了评分。
清单 6. 计算评分的响应声明
<responseDeclaration identifier="QUESTION1" cardinality="multiple"
baseType="identifier">
<correctResponse>
<value>A</value>
<value>D</value>
</correctResponse>
<mapping defaultValue="0" lowerBound="0" upperBound="1">
<mapEntry mapKey="A" mappedValue="0.5"/>
<mapEntry mapKey="B" mappedValue="-0.5"/>
<mapEntry mapKey="C" mappedValue="-0.5"/>
<mapEntry mapKey="D" mappedValue="0.5"/>
</mapping>
</responseDeclaration>
<itemBody>
<choiceInteraction responseIdentifier="QUESTION1" shuffle="false" maxChoices="0">
<prompt>Which are colors?</prompt>
<simpleChoice identifier="A">Red</simpleChoice>
<simpleChoice identifier="B">Small</simpleChoice>
<simpleChoice identifier="C">Soft</simpleChoice>
<simpleChoice identifier="D">Purple</simpleChoice>
</choiceInteraction>
</itemBody>
|
那么,如果学员给出了答案 A(红色)、B(小)和 D(紫色),评分将根据
<mapping> 计算如下:
(A) 0.5 + (B) -0.5 + (D) 0.5 = 0.5 。
您可能会感到迷惑,这个过程为什么不全部在
<responseDeclaration> 内完成。确定一个答案是否正确并计算评分也可以在
<responseProcessing> 部分中完成。在可以计算 答案和评分的情况下,似乎不必声明 正确的答案和评分(反之亦然)。
这里的根本原因在于,QTI 也要求标准适用于简单的情况,例如,一个直接忽略响应处理、只关注指定的正确响应的呈现引擎。 相同的推理也适用于 预定义的响应处理模板。
<outcomeDeclaration> 是 QTI 中与变量同等的部分。清单 7 给出了一个示例。
清单 7. 结果声明示例
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float">
<defaultValue>
<value baseType="float">0.5</value>
</defaultValue>
</outcomeDeclaration>
|
这段标记定义了一个称为
SCORE 的变量,其中包含单独一个
float,默认值为 0.5。默认值是可选的。如果您不提供默认值,则数值变量将初始化为 0.0,非数值变量将初始化为
NULL。
注意:
SCORE
是一个保留名称。它用于为环境提供一个数值评分,表示考生的题项总成绩。
您可以提供一个称为 <matchTable> 或 <interpolationTable> 的结构,为
<outcomeDeclaration> 添加更多智能。我从未看到过有人使用这些结构,大多数呈现引擎可能也不支持它们,因此这里不做解释。
题项的
<responseProcessing>
部分包含面向呈现引擎的说明,说明在用户提供了答案之后应该做些什么。这类说明可采用两种格式:
- 使用简单、基于 XML 的编程语言的程序或脚本
- 对预先定义的模板的引用,此模板也是响应处理编程语言中的一段脚本(因为模板是预先定义的,呈现引擎可以对其硬编码,如果您坚持使用这种选项,那么就不需要提供完整的脚本解释器。)
我们首先来看看响应处理脚本。清单 8 提供了一个此类脚本的示例。
清单 8. 响应处理的简单示例
<responseDeclaration identifier="RESPONSE_01" cardinality="single"
baseType="string">
<correctResponse>
<value>white</value>
</correctResponse>
</responseDeclaration>
<responseDeclaration identifier="RESPONSE_02" cardinality="single"
baseType="string">
<correctResponse>
<value>green</value>
</correctResponse>
</responseDeclaration>
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
<itemBody>
<p>Fill in the right colors:</p>
<p>Snow is
<textEntryInteraction responseIdentifier="RESPONSE_01" expectedLength="5"/>
and grass is
<textEntryInteraction responseIdentifier="RESPONSE_02" expectedLength="5"/>.
</p>
</itemBody>
<responseProcessing>
<responseCondition>
<responseIf>
<and>
<match>
<variable identifier="RESPONSE_01"/>
<correct identifier="RESPONSE_01"/>
</match>
<match>
<variable identifier="RESPONSE_02"/>
<correct identifier="RESPONSE_02"/>
</match>
</and>
<setOutcomeValue identifier="SCORE">
<baseValue baseType="integer">1.0</baseValue>
</setOutcomeValue>
</responseIf>
<responseElse>
<setOutcomeValue identifier="SCORE">
<baseValue baseType="integer">0.0</baseValue>
</setOutcomeValue>
</responseElse>
</responseCondition>
</responseProcessing>
|
该响应处理将根据指定的正确(最优)响应检查学员提供的两个响应的值。这是在
<match> 元素中完成的。两者必须同时正确,这将由外围的
<and>
元素保证。如果两者均正确,则
SCORE <outcomeDeclaration>
将设置为 1.0;否则将设置为 0.0。清单 9 提供了另一个略为复杂的示例。
清单 9. 较为复杂的响应处理示例
<responseDeclaration identifier="RESPONSE" cardinality="multiple"
baseType="identifier">
<correctResponse>
<value>A</value>
<value>C</value>
</correctResponse>
<mapping lowerBound="0.0" upperBound="1.0" defaultValue="0.0">
<mapEntry mapKey="A" mappedValue="0.5"/>
<mapEntry mapKey="B" mappedValue="-0.25"/>
<mapEntry mapKey="C" mappedValue="0.5"/>
<mapEntry mapKey="D" mappedValue="-0.25"/>
</mapping>
</responseDeclaration>
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
<outcomeDeclaration identifier="FEEDBACK" cardinality="single" baseType="identifier"/>
<outcomeDeclaration identifier="FEEDBACK_TRESHOLD" cardinality="single"
baseType="float">
<defaultValue>
<value baseType="float">0.75</value>
</defaultValue>
</outcomeDeclaration>
<itemBody>
<choiceInteraction responseIdentifier="RESPONSE" shuffle="true" maxChoices="0">
<prompt>Which countries are south of the USA?</prompt>
<simpleChoice identifier="A">Mexico</simpleChoice>
<simpleChoice identifier="B">Canada</simpleChoice>
<simpleChoice identifier="C">Brazil</simpleChoice>
<simpleChoice identifier="D">Norway</simpleChoice>
</choiceInteraction>
</itemBody>
<responseProcessing>
<responseCondition>
<responseIf>
<isNull>
<variable identifier="RESPONSE"/>
</isNull>
<setOutcomeValue identifier="SCORE">
<baseValue baseType="float">0.0</baseValue>
</setOutcomeValue>
<setOutcomeValue identifier="FEEDBACK">
<baseValue baseType="identifier">FAILURE</baseValue>
</setOutcomeValue>
</responseIf>
<responseElse>
<setOutcomeValue identifier="SCORE">
<mapResponse identifier="RESPONSE"/>
</setOutcomeValue>
<responseCondition>
<responseIf>
<gte>
<variable identifier="SCORE"/>
<variable identifier="FEEDBACK_TRESHOLD"/>
</gte>
<setOutcomeValue identifier="FEEDBACK">
<baseValue baseType="identifier">ANSWER_CORRECT</baseValue>
</setOutcomeValue>
</responseIf>
<responseElse>
<setOutcomeValue identifier="FEEDBACK">
<baseValue baseType="identifier">FAILURE</baseValue>
</setOutcomeValue>
</responseElse>
</responseCondition>
</responseElse>
</responseCondition>
</responseProcessing>
|
除了设置评分之外,上述响应处理还将一个名为 FEEDBACK 的
<outcomeDeclaration> 设置为
FAILURE
或
ANSWER_CORRECT。您可以使用这样的声明为用户提供正确的反馈。
响应处理的步骤如下:
-
确定一个答案是否存在(或许用户直接点击了 继续,而未提供答案)。如果存在,确定
<responseDeclaration>值是否为NULL(由<isNull>元素检查),SCORE和FEEDBACK将被设置为正确的值。 -
将
SCORE设置为<responseDeclaration的<mapping>提供的值(使用<mapResponse>元素)。 -
将
SCORE与FEEDBACK_TRESHOLD <outcomeDeclaration>(位于<gte>[大于或等于]元素中)设置的固定值对比,并相应地设置FEEDBACK。
除了您自己的声明之外,您还可以在响应处理中使用一些预先定义的变量:
-
duration. 用户用于回答问题的时间,以秒为单位。举例来说,使用此变量时,如果用户提供一个答案时所用时间过长,则可扣分。 -
nunAttempts和completionStatus. 在关于 自适应处理 的部分中介绍了这些变量。
即便您不熟悉编程或脚本,响应处理的编写也不复杂。您可以在 QTI 文档 IMS 问题与测试交互评估测试、部分和题项信息模型(参考资料 中提供了链接)中找到语言的完整定义,如您所见,由于采用了 XML,因此它较为繁冗,您必须编写大量代码才能实现有意义的操作。遗憾的是,这就是标准。
我在 响应声明 中已经提到,QTI 标准拥有面向简单响应处理的内置选项。举例来说,通过使用 <responseDeclaration> 中的正确响应,它就能确定给定答案是否正确,完全不需要执行任何脚本编程的响应处理。
这种方法允许在不违背标准的前提下处理简单的内容和附带的呈现引擎。
另外一项简化特就是响应处理模板。QTI 预先定义了三种模板,用于基本响应处理。这些模板使用固定 URI 标识,—例如:
<responseProcessing template="http://www.imsglobal.org/question/qti_v2p0/rptemplates/match_correct"/> |
实际脚本与这些 URI 结合使用。呈现引擎可以像处理脚本那样处理它们。为了帮助呈现引擎找到正确的模板,您可以像下面这样提供位置:
<responseProcessing template="..." templateLocation="/rptemplates/match_correct.xml/> |
只要满足以下条件,您就可以使用预先定义的模板:
- 操作仅包含一项交互
-
此操作的
<responseDeclaration>称为RESPONSE -
操作包含一个称为
SCORE的<outcomeDeclaration>,其类型为float
预先定义的模板包括:
-
Match_Correct:如果答案缺失或错误,将评分设置为 0.0,如果答案正确,将评分设置为 1.0。URI 是:http://www.imsglobal.org/question/qti_v2p0/rptemplates/match_correct
-
Map_Response:如果无答案,则将评分设置为 0.0;否则使用RESPONSE <responseDeclaration>内的映射。URI 是:http://www.imsglobal.org/question/qti_v2p1/rptemplates/map_response
-
Map_Response_Point:这与Map_Response基本相同,但类型是图形交互类型。它使用区域映射而非标识符映射。URI 是:http://www.imsglobal.org/question/qti_v2p1/rptemplates/map_response_point
您可以在响应处理脚本语言中表示所有预先定义的模板。如果您下载了 QTI 示例,模板脚本应已包含在内。例如,
清单 10
展示了
Map_Response 的代码。
清单 10. 预先定义的模板 Map_Response 的脚本
<responseProcessing>
<responseCondition>
<responseIf>
<isNull>
<variable identifier="RESPONSE"/>
</isNull>
<setOutcomeValue identifier="SCORE">
<baseValue baseType="integer">0</baseValue>
</setOutcomeValue>
</responseIf>
<responseElse>
<setOutcomeValue identifier="SCORE">
<mapResponse identifier="RESPONSE"/>
</setOutcomeValue>
</responseElse>
</responseCondition>
</responseProcessing>
|
并非一定要使用这些 QTI 预先定义的模板。如果内容生成器和呈现引擎生成器紧密耦合,那么最合理的做法就是定义自己的模板。
至此,我已经探讨了一个 QTI 题项的响应处理,例如学员与问题的一次性交互:显示问题、给出答案、计算评分。QTI 将这种类型的考试形式称为非自适应 题项。在另外一种情况下,您希望教会学员一些内容,使用问题作为教学的一种手段。此时,学员通常有多次回答问题的机会。并且能获得更为具体的反馈(“这种回答是错误的”、“我可以提示一下:...”),您可以根据常识的此时调整评分。
对于这种情况,QTI 定义了自适应 题项。自适应题项是通过在根元素中将
adaptive 属性设置为
true() 来指定的,如 清单 11 所示。
清单 11. 通过设置根元素的 adaptive 属性指定自适应题项
<assessmentItem adaptive="true" … > … </assessmentItem> |
在自适应题项中,与学员的交互不再是在提供答案后默认终止。而是可以通过两种方式结束:
- 在呈现引擎中定义某些内容(显式的 停止 按钮、计时器等)
-
响应处理会显示设置一个内置变量,称为
completionStatus
变量
completionStatus
拥有四种可能的
identifier 类型值:
completed、incomplete、not_attempted 和
unknown。如果您将其设置为
completed,那么交互就会终止。
对于自适应题项来说,另外一个非常方便的内置变量就是
numAttempts。可想而知,这个变量会计算用户尝试回答题项的次数。举例来说,
清单 12 展示了在用户尝试回答超过四次之后终止交互的响应处理片段。
清单 12. 使用 numAttempts 设置完成状态
<responseIf>
<gt>
<variable identifier="numAttempts"/>
<baseValue baseType="integer">4</baseValue>
</gt>
<setOutcomeValue identifier="completionStatus">
<baseValue baseType="identifier">completed</baseValue>
</setOutcomeValue>
</responseIf>
|
这篇文章探讨了 QTI 呈现引擎执行(或应该用于执行:良好的呈现引擎并不多见)响应和结果处理的方式:在学员回答了一个问题之后应该发生什么。在大多数情况下,应该给出成绩,但您也可以将其用于其他目的。
如果您不希望实现完整的 QTI 响应和响应处理,那么您仍然可以沿用标准,重新采用与给定的正确答案对比或者使用内置响应处理模板的方法。
学习
- IMS 网站:进一步了解 IMS 和 QTI 标准。
- IMS 问题与测试交互实现指南(IMS,2006 年 6 月):查看 QTI 版本 2 的示例。这些示例展示了系统应如何实现规范,并非只是对它们进行说明。
- IMS 问题与测试交互评估测试、部分和题项信息模型(IMS,2006 年 6 月):阅读本文,了解评估中使用的题项、部分和整个测试的信息模型。
-
XML 新手入门 可以获得学习 XML 所需的资源。
- developerWorks XML 专区:找到提升您在 XML 领域方面的技能所需的资源,包括 DTD、架构和 XSLT。查看 XML 技术库,获得广泛的技术文章和提示、教程、标准和 IBM Redbook。
- IBM XML 认证:了解如何成为 IBM 认证的 XML 和相关技术开发人员。
- developerWorks 技术活动 和 网络广播:通过这些活动随时把握技术动态。
- developerWorks on Twitter:立即加入,关注 developerWorks 的微博。
- developerWorks podcasts:收听面向软件开发人员的有趣访谈和讨论。
- 演示如何用 WebSphere Studio 快速开发Web Services:观看演示,范围从适合初学者的产品安装和设置一直到适合经验丰富的开发人员的高级功能。
获得产品和技术
- IBM 产品评估试用版软件:下载或 IBM SOA 人员沙箱,亲身体验 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 应用程序开发工具和中间件产品。
讨论
- developerWorks 个人资料:立即创建您的个人资源,并 设置关注列表。
- XML 专区论坛:参与任何 XML 相关讨论。
- developerWorks 中文社区:与其他 developerWorks 用户沟通,浏览开发人员驱动的博客、论坛、小组和 wiki。

Erik Siegel 是荷兰的一名自由 XML 专家。他在职业生涯中担任过许多职位—研究员、程序员、系统分析师、顾问。在过去的 5 年中,XML 逐渐走入他的生活。他的主要客户是出版业客户,他的 XML 工作包括顾问、培训、架构开发和 XSLT 编程。您可以访问 www.xatapult.com,找到有关 Erik 和他的公司的更多信息。