InfoPath list of countries for drop-down

Want a drop-down list of countries for use in your InfoPath form? The guys at forms on fire have kindly created an XML file which makes this easy.

  1. Save the file (countries or US states – we’ll work with countries from now on) from the link above;
  2. In InfoPath, add a new Drop-Down List Box control, then right-click it and choose Drop Down List Box Properties
  3. On the Data tab, under List box choices, choose Get choices from an external data source and click the Add… button to the right of Data source.
  4. In the Data Connection Wizard, Select Create a new connection to: and Receive data then click Next >.
  5. Choose XML Document then Next >.
  6. Click Resource Files…
  7. In the Resource Files dialogue, click the Add… button and choose the CountryLookup.xml file you downloaded above. Click Open, then OK.
  8. Back in the wizard, click Next >, enter a name for the data connection e.g CountryLookup and click Finish
  9. Back in the Drop Down List Box Properties dialogue we need to specify the name of the repeating entries in the xml file so click the button to the right of Entries and select the repeating group – in this case ‘country’:
    CountryLookup
  10. Click OK, then use the similar buttons to choose which fields you wish to use for the Value (what is saved when users choose this country) and Display Name (what they see in the box) – in this case, ‘name’. Click OK and test.

XML views in CakePHP 2.x

In a CakePHP project, I needed to extract an XML string from the database and display it as an XML page. The docs suggested this would be easy with the XmlView, but I struggled to get it to work. However,  after a fair amount of fiddling around, I found an easy way to display an XML view.

Here’s what I had to do:

  • Enable parsing of .xml extensions in routes.php:
    Router::parseExtensions('xml');
  • Set the viewClass to Xml in the controller:
    $this->viewClass = 'Xml';
  • Create a simple xml view in Views/YourController/xml/xml.ctp, and echo $xml in this view:
    <?php echo $xml; ?>
  • Back in the controller, set the XML string to the view:
    $this->set('xml', $xmlString);
  • Finally, render using the xml view you have just created (this must be after the ‘set’ line above):
    $this->render('xml');

Unfortunately, this does not take advantage of the _serialize key, which would mean you don’t need to create a view file at all, but I just couldn’t get this to work with an XML string, despite trying various combinations of CakePHP’s Xml Class functions.

Maths with QTI – Response Processing

From my experience, the responseProcessing section of a QTI XML file is the most complicated. It is the place where you check whether the user has given the correct response, deal with incorrect responses, and display the appropriate feedback. In theory it could be very simple, if you are just checking whether an answer is correct, showing the ‘correct’ feedback if it is and showing ‘incorrect’ feedback if it is not. However, it is possible to give much more tailored feedback than this, pointing users in the right direction if they have made a common mistake.

Another common use of the responseProcessing is to show a hint and/or a solution if the user requests it. For a generic structure for doing this, please see the Solution and Hint post.

responseProcessing Start and End

<responseProcessing>
<!-- Response processing goes here -->
</responseProcessing>

responseConditions

General Structure

This is the general structure for if…else if…else statements for dealing with responses. responseCondition statements can be nested within each other to create complex hierarchies of conditions.

<responseCondition>
   <responseIf>
   </responseIf>
   <responseElseIf>
   </responseElseIf>
   <responseElse>
   </responseElse>
</responseCondition>

Simple Example

In this example, the RESPONSE is tested for being NULL, in which case a score of 0 is given, and no feedback shown, so the user can just have another go. Next, RESPONSE is tested for being equal to ANSWER (i.e. the response is correct), in which case the CORRECT feedback is shown and the score is set to 1. Otherwise, the INCORRECT feedback is shown and the score set to 0.

<responseCondition>
   <!-- Is the response NULL? -->
   <responseIf>
      <isNull>
         <variable identifier="RESPONSE"/>
      </isNull>
      <setOutcomeValue identifier="SCORE">
         <baseValue baseType="float">0.0</baseValue>
      </setOutcomeValue>
   </responseIf>
   <responseElseIf>
      <!-- Is the response Correct? -->
      <equal toleranceMode="exact">
         <variable identifier="iAnswer"/>
         <variable identifier="RESPONSE"/>
      </equal>
      <setOutcomeValue identifier="FEEDBACK">
         <multiple>
            <baseValue baseType="identifier">CORRECT</baseValue>
         </multiple>
      <setOutcomeValue identifier="SCORE">
         <baseValue baseType="float">1.0</baseValue>
      </setOutcomeValue>
   </responseElseIf>
   <responseElse>
      <!-- Otherwise the response must be incorrect -->
      <setOutcomeValue identifier="FEEDBACK">
         <multiple>
            <baseValue baseType="identifier">INCORRECT</baseValue>
         </multiple>
      </setOutcomeValue>
      <setOutcomeValue identifier="SCORE">
         <baseValue baseType="float">0.0</baseValue>
      </setOutcomeValue>
   </responseElse>
</setOutcomeValue>

Feedback

Empty the Feedback Variable

This empties the feedback ‘multiple’ variable, so any previously shown feedback (from previous response) is removed before we process the current response. The EMPTY variable must have been declared in the Variable Declarations.

<setOutcomeValue identifier="FEEDBACK">
   <multiple>
      <variable identifier="EMPTY"/>
   </multiple>
</setOutcomeValue>

Add Feedback to the Feedback Variable

This defines the feedback sections that will be shown to the user. Multiple feedback sections can be shown by adding multiple identifiers.

<setOutcomeValue identifier="FEEDBACK">
   <multiple>
      <baseValue baseType="identifier">INCORRECT</baseValue>
      <baseValue baseType="identifier">NOTSIMP</baseValue>
   </multiple>
</setOutcomeValue>

Append Feedback to the Feedback Variable

If some feedback has already been defined and you want to add further feedback, you can append another feedback identifier as shown.

<setOutcomeValue identifier="FEEDBACK">
   <multiple>
      <variable identifier="FEEDBACK"/>
      <baseValue baseType="identifier">SEEN-HINT</baseValue>
   </multiple>
</setOutcomeValue>

Comparisons

Equal

This simply compares whether two numerical values are equal. If ‘toleranceMode’ is set to exact, the values must be exactly equal. toleranceMode can also be set to absolute or relative, in which case the ‘tolerance’ must be specified. See the specification for more information.

<equal toleranceMode="exact">
   <variable identifier="iAnswer"/>
   <variable identifier="RESPONSE"/>
</equal>

EqualRounded

This compares whether two values are equal, to a specified level of rounding. The roundingMode can either be decimalPlaces or significantFigures.

<equalRounded roundingMode="decimalPlaces" figures="0">
   <variable identifier="RESPONSE"/>
   <variable identifier="iAnswer"/>
</equalRounded>

Substring contains

<substring caseSensitive="false">
   <baseValue baseType="string">+</baseValue>
   <variable identifier="printMath"/>
</substring>

isNull

This tests whether a value is null.

<isNull>
   <variable identifier="RESPONSE"/>
</isNull>

Custom Operator

Custom operators can be used to carry out more complicated tests, e.g. comparing mathematical responses using the MathAssess engine. The ‘action’ can take one of three values:

  • equal: algebraic equivalence (e.g. factorised and expanded forms are equivalent)
  • syntequal: syntactical equality (e.g. factorised and expanded forms are not syntactically equal)
  • code: allows custom comparison code to be provided

As an example of the difference between equal and syntequal, 1/2 and 2/4 are equal, but not syntequal. 2(x+1) and 2x+2 are equal, but not syntequal.

<customOperator class="org.qtitools.mathassess.CasCompare" ma:action="equal" ma:syntax="text/x-maxima">
   <variable identifier="mAnswer"/>
   <variable identifier="RESPONSE"/>
</customOperator>

The following example of a ‘code’ action tests whether the sum of the two response and answer is 0, i.e. the response is correct, but has the wrong sign.

<customOperator class="org.qtitools.mathassess.CasCompare" ma:action="code" ma:code="is(equal($1+$2,0));" ma:syntax="text/x-maxima">
   <variable identifier="RESPONSE"/>
   <variable identifier="mAnswer"/>
</customOperator>

Operators

And Or

As you would expected, placing two comparisons within an ‘and’ operator gives a true result only if both comparisons evaluate to true. Placing two comparisons within an ‘or’ gives a true result if either (or both) of the comparisons evaluate to true. For or, just use the following snippet and change the <and>/</and> tags to <or>/</or>

<and>
   <equal toleranceMode="exact">
      <variable identifier="iAnswer1"/>
      <variable identifier="RESPONSE1"/>
   </equal>
   <equal toleranceMode="exact">
      <variable identifier="iAnswer2"/>
      <variable identifier="RESPONSE2"/>
   </equal>
</and>

Not

The ‘not’ operators gives the ‘logical negative’ (i.e. opposite, e.g. true => false) of the subexpression. The following snippet will return true if the value of RESPONSE is not null.

<not>
   <isNull>
      <variable identifier="RESPONSE"/>
   </isNull>
</not>

 

Maths with QTI – QTI XML Structure and Building Blocks Resource

We have recently started using QTI, specifically Uniqurate and QTIWorks, to write maths questions for delivery to students. Uniqurate can be used to write basic questions, including maths questions with numerical answers and simple randomisation of values. However, to incorporate more complex randomisation, e.g. randomising variable letters, to allow mathematical expressions to be given as answers and to do various other more complex things with maths questions, it is necessary to write (or, preferably, modify someone else’s!) QTI XML. This can get quite complicated and I have found some aspects of it difficult to get stuck into. I find that I know that something is possible, but it can take some time to pin down exactly how to do it, and I usually copy code from other questions. (Many thanks to Dr Sue Milne from ELandWeb for providing extensive help, both by giving access to her questions and answering many QTI-related queries)

One thing that I keep wishing for is a resource containing reusable blocks of QTI code that could be used to build a question. I believe that such a resource does not currently exist, so I have decided to start to write one, the links to which can be found below.

At this point I should make the disclaimer that I am still early on in my QTI journey, so I am no expert, and can by no means guarantee that this resource will be correct, but I will try to improve and extend it as I get to know the QTI specification better. The posts based on the XML snippets that I have been using, and therefore they are far from being a complete resourse. However, I hope they are useful to anyone getting started with QTI. Please feel free to suggest additions and corrections.

  1. QTI XML Basic Structure
  2. Variable Declarations
  3. Template Processing
  4. Item Body
  5. Response Processing
  6. Solution and Hint
  7. Modifying assessment.xml (for Assessments created in Uniqurate)

Maths with QTI – QTI XML Basic Structure

Please note that this is a work in progress!

This is the first of my QTI XML Building Blocks posts, where I will give the basic structure of an assessment item in a QTI XML file, that can be used as a framework that can be filled in with the building blocks that I will cover in future posts. This is very much a work in progress and I can’t promise everything is correct. At this stage I am just trying to create something that is useful to me, and putting it out there in case it is useful to anyone else!

So, here is the basic structure of a QTI XML document (or the basic structure I’ve been using/copying for writing questions):

<?xml version="1.0" encoding="UTF-8"?>

<!-- Define question properties -->
<!-- Some of these are obvious, others are XML namespace definitions - not all of these are generally needed 
   adaptive - if set to false, only one attempt is allowed, so this is best for summative items. If set to true, multiple attempts are allowed and the feedback/outcomes can be changed, and this is better for formative items, where a user can have multiple goes. This should not be confused with an adaptive test, where the questions presented change depending on a user's answers to previous questions, although a similar thing can be achieved within an adaptive item.
-->
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1"
   xmlns:m="http://www.w3.org/1998/Math/MathML"
   xmlns:xi="http://www.w3.org/2001/XInclude"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess"
   xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd http://mathassess.qtitools.org/xsd/mathassess mathassess.xsd">
   xml:lang="en"
   adaptive="true"
   timeDependent="false"
   identifier="questionidentifier"
   title="Question Title">

   <!-- VARIABLE DECLARATIONS -->
   <!-- Here we define all of the variables that are going to be used in the question -->

   <!-- Response Declarations -->
   <!-- These are the variables used in response processing, including those for storing the response(s) given by the user -->
   <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="integer"/>

   <!-- Outcome Declarations -->
   <!-- These are the variables used for returning an outcome to the user, e.g. score, feedback -->
   <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="integer"/>

   <!-- Template Declarations -->
   <!-- These are the variables used for creating the question, e.g. the variables used for randomising values within a question -->
   <templateDeclaration identifier="iA" cardinality="single" baseType="integer" mathVariable="true"/>

   <!-- TEMPLATE PROCESSING -->
   <templateProcessing>
      <!-- Here template variables are assigned values, constraints are defined etc -->
   </templateProcessing>

   <!-- ITEM BODY -->
   <itemBody>
      <!-- The itemBody contains the content of the item, including the question, interactions, feedback sections (which are initially hidden) etc  -->
   </itemBody>

   <!-- RESPONSE PROCESSING -->
   <responseProcessing>
      <!-- Here the user's response is assessed, compared the correct answer etc, and outcome variable, e.g. score and which feedback to show, are set -->
   </responseProcessing>
</assessmentItem>