Articles Archive
Articles Search
Director Wiki
 

Creating a Multiple Choice Quiz Using XML, Part 1

July 17, 2001
by Will Turnage

Dear Handyman,

I need to make an multiple-choice quiz. Can you help me? Thanks,

About 50 Director Developers

Dear Everyone,

One of the most common questions I get is from people who need to create a multiple choice quiz. Everyone seems to have his or her own different requirements for what the quiz needs to do, so these next two columns will walk you through the steps on how to build your own quiz from scratch.

The key to building a successful quiz engine is in its reusability, that is, the ability to retrieve your questions from outside the Director movie. This way, you can update the content of your quiz without having to change your Director code. There are different ways that you can keep the quiz questions outside of Director. One option is to create a specially formatted text file containing the quiz questions, and another valid approach would be to store all of the questions in a database and have the Director movie retrieve the questions from there. For this column, though, the emphasis is going to be on using an external XML file to hold your questions.

The biggest benefit to using an XML file to store your quiz questions is that you can create other applications to read the same text file. For instance, you could create a quiz in Flash and have it read the same XML file as your Director movie. But enough blabbing, let's get to the actual code. You should start with the XML file containing your questions. In this example, the XML file will look like this.

<?xml version="1.0"?>
<quiz>
<question>
<questionText>Who is the author of this column?</questionText>
<incorrect>Pat McClellan</incorrect>
<incorrect>Darrel Plant</incorrect>
<incorrect>Gary Rozensweig</incorrect>
<correct>Will Turnage</correct>
</question>
<question>
<questionText>Who writes Director Online's Lingo Lounge column?</questionText>
<incorrect>Pat McClellan</incorrect>
<incorrect>Darrel Plant</incorrect>
<correct>Gary Rozensweig</correct>
<incorrect>Will Turnage</incorrect>
</question>
<question>
<questionText>Who is Director Online's Technical Editor?</questionText>
<incorrect>Pat McClellan</incorrect>
<correct>Darrel Plant</correct>
<incorrect>Gary Rozensweig</incorrect>
<incorrect>Will Turnage</incorrect>
</question>
</quiz>

This XML document contains the information for three different questions. For each question, there is one correct answer and three incorrect answers. This XML file can be created in any text editor like SimpleText or Notepad.

To bring this data inside of Director, you should use Director's XML Parser Xtra. This can be done at any point in your movie in a single frame script using this code:

property pXMLObj
global gQuestions

on beginSprite me
  pXMLObj = new (xtra "XMLParser")
  pXMLObj.parseURL (the moviePath & "questions.xml")
end

on endSprite me
  pXMLObj = 0
end

on exitFrame me
  if pXMLObj.doneParsing () then
    gQuestions = pXMLObj.makeList ()
  else
    go the frame
  end if
end

In this behavior, you start by creating a new instance of Director's XML Parser Xtra. Then, you tell the Xtra to retrieve the contents of an XML file. In this case, that file is named questions.xml, and it's located in the same folder as your movie. You don't have to use a relative file name though, you can refer to a URL if you want. Then, on each exitFrame you check to see if the XML Xtra is finished parsing the XML file. If it's done, you convert the retrieved XML data into a property list using the XML Xtra's built-in makeList function. And if the Xtra isn't done parsing, your movie just loops on the frame until the parsing is done.

Once you've got your list of data, if you look at it, you'll see that it's pretty complex, like this:

["ROOT OF XML DOCUMENT": ["!ATTRIBUTES": [:], "quiz": ["!ATTRIBUTES": [:], "question": ["!ATTRIBUTES": [:], "questionText": ["!ATTRIBUTES": [:], "!CHARDATA": "Who is the author of this column?"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Pat McClellan"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Darrel Plant"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Gary Rozensweig"], "correct": ["!ATTRIBUTES": [:], "!CHARDATA": "Will Turnage"]], "question": ["!ATTRIBUTES": [:], "questionText": ["!ATTRIBUTES": [:], "!CHARDATA": "Who writes Director Online's Lingo Lounge column?"], "incorrect": [;"!ATTRIBUTES": [:], "!CHARDATA": "Pat McClellan"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Darrel Plant"], "correct": ["!ATTRIBUTES": [:], "!CHARDATA": "Gary Rozensweig"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Will Turnage"]], "question": ["!ATTRIBUTES": [:], "questionText": ["!ATTRIBUTES": [:], "!CHARDATA": "Who is Director Online's Technical Editor?"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Pat McClellan"], "correct": ["!ATTRIBUTES": [:], "!CHARDATA": "Darrel Plant"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Gary Rozensweig"], "incorrect": ["!ATTRIBUTES": [:], "!CHARDATA": "Will Turnage"]]]]]

While this XML list can be fairly tedious to browse, you might want to consider making the list a bit more manageable, by parsing the list and removing unnecessary attribute data (see the formatQuestionList handler in the sample movie):

[[#questionText: "Who is the author of this column?", #incorrect: "Pat McClellan", #incorrect: "Darrel Plant", #incorrect: "Gary Rozensweig", #correct: "Will Turnage"], [#questionText: "Who writes Director Online's Lingo Lounge column?", #incorrect: "Pat McClellan", #incorrect: "Darrel Plant", #correct: "Gary Rozensweig", #incorrect: "Will Turnage"], [#questionText: "Who is Director Online's Technical Editor?", #incorrect: "Pat McClellan", #correct: "Darrel Plant", #incorrect: "Gary Rozensweig", #incorrect: "Will Turnage"]]

This step in the process is optional, but it does have a few advantages. The first advantage is that the list is a bit easier to read so that it might make your debugging a bit easier. The other advantage is that when you rebuild the list, you can also randomize the questions if you want. Or you could just randomize the answers, or you could randomize both. But the important thing is that you now have all of your quiz questions and answers in a Director list instead of in an external file.

Once you have this list containing all of your questions and answers, then displaying them on screen isn't too difficult.

global gQuestions, gCurrentQuestionNum

on displayCurrentQuestion
  tempList = gQuestions[gCurrentQuestionNum].duplicate ()
  member ("questions").text = gCurrentQuestionNum & "." && tempList.questionText
  tempList.deleteProp (#questionText)
  repeat with i = 1 to tempList.count
    member ("answer" & i).text = numToChar (96+i) & ")" && tempList[i]
  end repeat
end

This handler starts by making a duplicate of the current question in your list of question. Next it take the text for the question, and puts it into a text member named questions. Note that it also adds the number of the question to the beginning of the text. After doing this, the handler deletes the question from the list, leaving just the answers. It then repeats through each of the answers, putting their text in separate members named answer1, answer2, answer3 and so on. Note that it also adds the text a), b), c) and so on in front of each answer as well.

When all of this is done, you get a movie that looks like this:

Next week, you'll learn how to pick the answer in your quiz, give user feedback, and keep track of people's scores.

A sample Director 8 movie and XML file (as well as an HTML and DCR file) are available for download in Macintosh or Windows format. Because this movie accesses external files, running from your hard drive within a browser requires that the movie path contain dswmedia.

Will Turnage is a multimedia programmer based in New York City. In addition to his weekly role as Director Online's Multimedia Handyman, he is also the Technology Director for Sony Music's Client Side Technologies Group. You can read more about his work at http://will.turnage.com/.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.