function questions_import_qti_extract_info in Quiz 6.6
Same name and namespace in other branches
- 6.3 includes/questions_import/questions_import.admin.inc \questions_import_qti_extract_info()
Given a QTI 1.2 XML file, extract quiz questions.
1 call to questions_import_qti_extract_info()
- questions_import_submit_qti12 in includes/
questions_import/ questions_import.admin.inc - This function imports questions from Question and Test Interoperability (QTI) format file.
File
- includes/
questions_import/ questions_import.admin.inc, line 578 - Administration file for Questions Import module
Code
function questions_import_qti_extract_info($file) {
$items = array();
foreach (qp($file, 'item') as $item) {
$title = $item
->attr('title');
$type = $item
->find('itemmetadata>qmd_itemtype')
->text();
$body = $item
->end()
->find('presentation>material>mattext');
if ($body
->attr('texttype') == 'text/html') {
$bodytext = $body
->text();
if (strpos($bodytext, '<html') === FALSE) {
drupal_set_message('Adding HTML', 'status');
$bodytext = '<html>' . $bodytext . '</html>';
}
// Load here so that errors are caught by Drupal (which has no exception handler.)
$doc = new DOMDocument();
$doc
->loadHTML($bodytext);
$html = qp($doc, 'body');
$contents = $html
->get(0)->childNodes;
// Extract content from HTML and put it in a temp document.
$newdoc = qp('<?xml version="1.0"?><div id="qti-question-body"/>');
$i = 0;
while ($node = $contents
->item($i++)) {
$newdoc
->append($node);
}
$out = $newdoc
->html();
// This leaves off XML declaration.
}
else {
$out = $body
->text();
}
$new_item = array(
'title' => $title,
'type' => $type,
'content' => $out,
);
// Handle multiple choice questions:
if (strtolower($type) == 'multiple choice') {
$answers = array();
// First, get all anssers and loop through them.
$answerstexts = $item
->parent('item')
->find('response_lid>render_choice>response_label>material>mattext');
foreach ($answerstexts as $answertext) {
// As we find each answer, grab a bunch of related data. Processing-wise, this is not terribly
// efficient, since we are hoping back and forth inside of the document. However, it is much easier
// to do this all together.
$text = $answertext
->text();
$index = $answertext
->parent('response_label')
->attr('ident');
// This filter grabs the answer setting by index. Most of the time, index appears to be
// an alpha char.
$contains_filter = 'resprocessing>respcondition>conditionvar>varequal:contains(' . $index . ')';
$correct = $answertext
->parent('item')
->find($contains_filter)
->parent('respcondition')
->find('setvar')
->text();
if ($correct == 0) {
$feedback = $answertext
->parent('item')
->find('itemfeedback[ident="Wrong Answer"]>material>mattext')
->text();
}
else {
$feedback = 'Correct';
}
// Store all of this in an array.
$answers[] = array(
'text' => $text,
'index' => $index,
'is_correct' => $correct,
'feedback' => $feedback,
);
}
// Store answers
$new_item['answers'] = $answers;
}
// Store questions
$items[] = $new_item;
}
return $items;
}