]> git.mjollnir.org Git - moodle.git/commitdiff
Adding xml export
authorthepurpleblob <thepurpleblob>
Fri, 6 Aug 2004 14:59:45 +0000 (14:59 +0000)
committerthepurpleblob <thepurpleblob>
Fri, 6 Aug 2004 14:59:45 +0000 (14:59 +0000)
mod/quiz/format/xml/format.php [new file with mode: 0755]

diff --git a/mod/quiz/format/xml/format.php b/mod/quiz/format/xml/format.php
new file mode 100755 (executable)
index 0000000..f9aad38
--- /dev/null
@@ -0,0 +1,228 @@
+<?php // $Id$
+//
+///////////////////////////////////////////////////////////////
+// XML import/export
+//
+//////////////////////////////////////////////////////////////////////////
+// Based on default.php, included by ../import.php
+
+class quiz_file_format extends quiz_default_format {
+
+function indent_xhtml($source, $indenter = ' ') { 
+    // xml tidier-upper
+    // (c) Ari Koivula http://ventionline.com
+    
+    // Remove all pre-existing formatting. 
+    // Remove all newlines. 
+    $source = str_replace("\n", '', $source); 
+    $source = str_replace("\r", '', $source); 
+    // Remove all tabs. 
+    $source = str_replace("\t", '', $source); 
+    // Remove all space after ">" and before "<". 
+    $source = ereg_replace(">( )*", ">", $source); 
+    $source = ereg_replace("( )*<", "<", $source); 
+
+    // Iterate through the source. 
+    $level = 0; 
+    $source_len = strlen($source); 
+    $pt = 0; 
+    while ($pt < $source_len) { 
+        if ($source{$pt} === '<') { 
+            // We have entered a tag. 
+            // Remember the point where the tag starts. 
+            $started_at = $pt; 
+            $tag_level = 1; 
+            // If the second letter of the tag is "/", assume its an ending tag. 
+            if ($source{$pt+1} === '/') { 
+                $tag_level = -1; 
+            } 
+            // If the second letter of the tag is "!", assume its an "invisible" tag. 
+            if ($source{$pt+1} === '!') { 
+                $tag_level = 0; 
+            } 
+            // Iterate throught the source until the end of tag. 
+            while ($source{$pt} !== '>') { 
+                $pt++; 
+            } 
+            // If the second last letter is "/", assume its a self ending tag. 
+            if ($source{$pt-1} === '/') { 
+                $tag_level = 0; 
+            } 
+            $tag_lenght = $pt+1-$started_at; 
+             
+            // Decide the level of indention for this tag. 
+            // If this was an ending tag, decrease indent level for this tag.. 
+            if ($tag_level === -1) { 
+                $level--; 
+            } 
+            // Place the tag in an array with proper indention. 
+            $array[] = str_repeat($indenter, $level).substr($source, $started_at, $tag_lenght); 
+            // If this was a starting tag, increase the indent level after this tag. 
+            if ($tag_level === 1) { 
+                $level++; 
+            } 
+            // if it was a self closing tag, dont do shit. 
+        } 
+        // Were out of the tag. 
+        // If next letter exists... 
+        if (($pt+1) < $source_len) { 
+            // ... and its not an "<". 
+            if ($source{$pt+1} !== '<') { 
+                $started_at = $pt+1; 
+                // Iterate through the source until the start of new tag or until we reach the end of file. 
+                while ($source{$pt} !== '<' && $pt < $source_len) { 
+                    $pt++; 
+                } 
+                // If we found a "<" (we didnt find the end of file) 
+                if ($source{$pt} === '<') { 
+                    $tag_lenght = $pt-$started_at; 
+                    // Place the stuff in an array with proper indention. 
+                    $array[] = str_repeat($indenter, $level).substr($source, $started_at, $tag_lenght); 
+                } 
+            // If the next tag is "<", just advance pointer and let the tag indenter take care of it. 
+            } else { 
+                $pt++; 
+            } 
+        // If the next letter doesnt exist... Were done... well, almost.. 
+        } else { 
+            break; 
+        } 
+    } 
+    // Replace old source with the new one we just collected into our array. 
+    $source = implode($array, "\n"); 
+    return $source; 
+} 
+
+
+function export_file_extension() {
+    // override default type so extension is .xml
+    
+    return ".xml";
+}
+
+function get_qtype( $type_id ) {
+    // translates question type code number into actual name
+   
+    switch( $type_id ) {
+    case TRUEFALSE:
+        $name = 'truefalse';
+        break;
+    case MULTICHOICE:
+        $name = 'multichoice';
+        break;
+    case SHORTANSWER:
+        $name = 'shortanswer';
+        break;
+    case NUMERICAL:
+        $name = 'numerical';
+        break;
+    case MATCH:
+        $name = 'matching';
+        break;
+    case DESCRIPTION:
+        $name = 'description';
+        break;
+    case MULTIANSWER:
+        $name = 'cloze';
+        break;
+    default:
+        $name = '';
+        error( "question type $type_id is not defined in get_qtype" );
+    }
+    return $name;
+}
+
+function writetext( $raw ) {
+    // generates <text></text> tags, processing raw text therein 
+
+    // for now, don't allow any additional tags in text 
+    // otherwise xml rules would probably get broken
+    $raw = strip_tags( $raw );
+
+    return "<text>$raw</text>\n";
+}
+
+function writequestion( $question ) {
+    // turns question into string
+    // question reflects database fields for general question and specific to type
+
+    // initial string;
+    $expout = "";
+
+    // add comment
+    $expout .= "\n\n<!-- question: $question->id  name: $question->name -->\n";
+
+    // add opening tag
+    $question_type = $this->get_qtype( $question->qtype );
+    $name_text = $this->writetext( $question->name );
+    $question_text = $this->writetext( $question->questiontext );
+    $expout .= "<question type=\"$question_type\">\n";   
+    $expout .= "<name>".$this->writetext($name_text)."</name>\n";
+    $expout .= "<questiontext>".$this->writetext($question_text)."</questiontext>\n";   
+
+    // output depends on question type
+    switch($question->qtype) {
+    case TRUEFALSE:
+        $true_percent = round( $question->trueanswer->fraction * 100 );
+        $false_percent = round( $question->falseanswer->fraction * 100 );
+        // true answer
+        $expout .= "<answer fraction=\"$true_percent\">\n";
+        $expout .= $this->writetext("true")."\n";
+        $expout .= "<feedback>".$this->writetext( $question->trueanswer->feedback )."</feedback>\n";
+        $expout .= "</answer>\n";
+
+
+        // false answer
+        $expout .= "<answer fraction=\"$false_percent\">\n";
+        $expout .= $this->writetext("false")."\n";
+        $expout .= "<feedback>".$this->writetext( $question->falseanswer->feedback )."</feedback>\n";
+        $expout .= "</answer>\n";
+        break;
+    case MULTICHOICE:
+        foreach($question->answers as $answer) {
+            $percent = round( $answer->fraction * 100 );
+            $expout .= "<answer fraction=\"$percent\">\n";
+            $expout .= $this->writetext( $answer->answer );
+            $expout .= "<feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
+            $expout .= "</answer>\n";
+            }
+        break;
+    case SHORTANSWER:
+        foreach($question->answers as $answer) {
+            $percent = 100 * $answer->fraction;
+            $expout .= "<answer fraction=\"$percent\">\n";
+            $expout .= $this->writetext( $answer->answer );
+            $expout .= "<feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
+            $expout .= "</answer>\n";
+        }
+        break;
+    case NUMERICAL:
+        $expout .= "<min>$question->min</min>\n";
+        $expout .= "<max>$question->max</max>\n";
+        $expout .= "<feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
+        break;
+    case MATCH:
+        foreach($question->subquestions as $subquestion) {
+            $expout .= "<subquestion>\n";
+            $expout .= $this->writetext( $subquestion->questiontext );
+            $expout .= "<answer>".$this->writetext( $subquestion->answertext )."</answer>\n";
+            $expout .= "</subquestion>\n";
+        }
+        break;
+    case DESCRIPTION:
+        $expout .= "<!-- DESCRIPTION type is not supported -->\n";
+        break;
+    case MULTIANSWER:
+        $expout .= "<!-- CLOZE type is not supported -->\n";
+        break;
+    default:
+        error( "No handler for qtype $question->qtype for GIFT export" );
+    }
+    // close the question tag
+    $expout .= "</question>\n";
+    // run through xml tidy function
+    return $this->indent_xhtml( $expout, '  ' ); 
+}
+}
+
+?>