ILIAS  Release_4_2_x_branch Revision 61807
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilQTIParser.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 include_once("./classes/class.ilSaxParser.php");
25 
26 define ("IL_MO_PARSE_QTI", 1);
27 define ("IL_MO_VERIFY_QTI", 2);
28 
38 class ilQTIParser extends ilSaxParser
39 {
40  var $lng;
42  var $path;
43  var $items;
44  var $item;
45  var $depth;
51  var $material;
52  var $matimage;
53  var $response;
55  var $outcomes;
56  var $decvar;
58  var $setvar;
61  var $flow_mat;
62  var $flow;
64  var $mattext;
65  var $sametag;
70  var $qpl_id;
71  var $tst_id;
79  var $in_assessment = FALSE;
80  var $section;
84  var $in_objectives = FALSE;
85 
86  var $founditems = array();
87  var $verifyroot = false;
94 
102  // TODO: The following line gets me an parse error in PHP 4, but I found no hint that pass-by-reference is forbidden in PHP 4 ????
103  function ilQTIParser($a_xml_file, $a_mode = IL_MO_PARSE_QTI, $a_qpl_id = 0, $a_import_idents = "")
104  {
105  global $lng;
106 
107  $this->setParserMode($a_mode);
108 
109  parent::ilSaxParser($a_xml_file);
110 
111  $this->qpl_id = $a_qpl_id;
112  $this->import_idents = array();
113  if (is_array($a_import_idents))
114  {
115  $this->import_idents =& $a_import_idents;
116  }
117 
118  $this->lng =& $lng;
119  $this->hasRootElement = FALSE;
120  $this->import_mapping = array();
121  $this->assessments = array();
122  $this->assessment = NULL;
123  $this->section = NULL;
124  $this->path = array();
125  $this->items = array();
126  $this->item = NULL;
127  $this->depth = array();
128  $this->do_nothing = FALSE;
129  $this->qti_element = "";
130  $this->in_presentation = FALSE;
131  $this->in_objectives = FALSE;
132  $this->in_reponse = FALSE;
133  $this->render_type = NULL;
134  $this->render_hotspot = NULL;
135  $this->response_label = NULL;
136  $this->material = NULL;
137  $this->response = NULL;
138  $this->assessmentcontrol = NULL;
139  $this->objectives = NULL;
140  $this->matimage = NULL;
141  $this->resprocessing = NULL;
142  $this->outcomes = NULL;
143  $this->decvar = NULL;
144  $this->respcondition = NULL;
145  $this->setvar = NULL;
146  $this->displayfeedback = NULL;
147  $this->itemfeedback = NULL;
148  $this->flow_mat = array();
149  $this->question_counter = 1;
150  $this->flow = 0;
151  $this->gap_index = 0;
152  $this->presentation = NULL;
153  $this->mattext = NULL;
154  $this->matapplet = NULL;
155  $this->sametag = FALSE;
156  $this->in_assessment = FALSE;
157  $this->characterbuffer = "";
158  $this->metadata = array("label" => "", "entry" => "");
159  }
160 
161  function setTestObject(&$a_tst_object)
162  {
163  $this->tst_object =& $a_tst_object;
164  if (is_object($a_tst_object))
165  {
166  $this->tst_id = $this->tst_object->getId();
167  }
168  }
169 
170  function setParserMode($a_mode = IL_MO_PARSE_QTI)
171  {
172  $this->parser_mode = $a_mode;
173  $this->founditems = array();
174  $this->verifyroot = false;
175  $this->verifyqticomment = 0;
176  $this->verifymetadatafield = 0;
177  $this->verifyfieldlabel = 0;
178  $this->verifyfieldentry = 0;
179  $this->verifyfieldlabeltext = "";
180  $this->verifyfieldentrytext = "";
181  $this->question_counter = 1;
182  }
183 
189  function setHandlers($a_xml_parser)
190  {
191  xml_set_object($a_xml_parser,$this);
192  xml_set_element_handler($a_xml_parser,'handlerBeginTag','handlerEndTag');
193  xml_set_character_data_handler($a_xml_parser,'handlerCharacterData');
194  }
195 
196  function startParsing()
197  {
198  $this->question_counter = 1;
200  return FALSE;
201  }
202 
203  function getParent($a_xml_parser)
204  {
205  if ($this->depth[$a_xml_parser] > 0)
206  {
207  return $this->path[$this->depth[$a_xml_parser]-1];
208  }
209  else
210  {
211  return "";
212  }
213  }
214 
218  function handlerBeginTag($a_xml_parser,$a_name,$a_attribs)
219  {
220  switch ($this->parser_mode)
221  {
222  case IL_MO_PARSE_QTI:
223  $this->handlerParseBeginTag($a_xml_parser, $a_name, $a_attribs);
224  break;
225  case IL_MO_VERIFY_QTI:
226  $this->handlerVerifyBeginTag($a_xml_parser, $a_name, $a_attribs);
227  break;
228  }
229  }
230 
234  function handlerParseBeginTag($a_xml_parser,$a_name,$a_attribs)
235  {
236  if ($this->do_nothing) return;
237  $this->sametag = FALSE;
238  $this->characterbuffer = "";
239  $this->depth[$a_xml_parser]++;
240  $this->path[$this->depth[$a_xml_parser]] = strtolower($a_name);
241  $this->qti_element = $a_name;
242 
243  switch (strtolower($a_name))
244  {
245  case "assessment":
246  include_once ("./Services/QTI/classes/class.ilQTIAssessment.php");
247  $this->assessment =& $this->assessments[array_push($this->assessments, new ilQTIAssessment())-1];
248  $this->in_assessment = TRUE;
249  if (is_array($a_attribs))
250  {
251  foreach ($a_attribs as $attribute => $value)
252  {
253  switch (strtolower($attribute))
254  {
255  case "title":
256  $this->assessment->setTitle($value);
257  break;
258  case "ident":
259  $this->assessment->setIdent($value);
260  break;
261  }
262  }
263  }
264  break;
265  case "assessmentcontrol":
266  include_once ("./Services/QTI/classes/class.ilQTIAssessmentcontrol.php");
267  $this->assessmentcontrol = new ilQTIAssessmentcontrol();
268  if (is_array($a_attribs))
269  {
270  foreach ($a_attribs as $attribute => $value)
271  {
272  switch (strtolower($attribute))
273  {
274  case "solutionswitch":
275  $this->assessmentcontrol->setSolutionswitch($value);
276  break;
277  case "hintswitch":
278  $this->assessmentcontrol->setHintswitch($value);
279  break;
280  case "feedbackswitch":
281  $this->assessmentcontrol->setFeedbackswitch($value);
282  break;
283  }
284  }
285  }
286  break;
287  case "objectives":
288  include_once ("./Services/QTI/classes/class.ilQTIObjectives.php");
289  $this->objectives = new ilQTIObjectives();
290  $this->in_objectives = TRUE;
291  break;
292  case "section":
293  include_once ("./Services/QTI/classes/class.ilQTISection.php");
294  $this->section = new ilQTISection();
295  break;
296  case "itemmetadata":
297  $this->in_itemmetadata = TRUE;
298  break;
299  case "qtimetadatafield":
300  $this->metadata = array("label" => "", "entry" => "");
301  break;
302  case "flow":
303  include_once ("./Services/QTI/classes/class.ilQTIFlow.php");
304  $this->flow++;
305  break;
306  case "flow_mat":
307  include_once ("./Services/QTI/classes/class.ilQTIFlowMat.php");
308  array_push($this->flow_mat, new ilQTIFlowMat());
309  break;
310  case "itemfeedback":
311  include_once ("./Services/QTI/classes/class.ilQTIItemfeedback.php");
312  $this->itemfeedback = new ilQTIItemfeedback();
313  if (is_array($a_attribs))
314  {
315  foreach ($a_attribs as $attribute => $value)
316  {
317  switch (strtolower($attribute))
318  {
319  case "ident":
320  $this->itemfeedback->setIdent($value);
321  break;
322  case "view":
323  $this->itemfeedback->setView($value);
324  break;
325  }
326  }
327  }
328  break;
329  case "displayfeedback":
330  include_once ("./Services/QTI/classes/class.ilQTIDisplayfeedback.php");
331  $this->displayfeedback = new ilQTIDisplayfeedback();
332  if (is_array($a_attribs))
333  {
334  foreach ($a_attribs as $attribute => $value)
335  {
336  switch (strtolower($attribute))
337  {
338  case "feedbacktype":
339  $this->displayfeedback->setFeedbacktype($value);
340  break;
341  case "linkrefid":
342  $this->displayfeedback->setLinkrefid($value);
343  break;
344  }
345  }
346  }
347  break;
348  case "setvar":
349  include_once ("./Services/QTI/classes/class.ilQTISetvar.php");
350  $this->setvar = new ilQTISetvar();
351  if (is_array($a_attribs))
352  {
353  foreach ($a_attribs as $attribute => $value)
354  {
355  switch (strtolower($attribute))
356  {
357  case "action":
358  $this->setvar->setAction($value);
359  break;
360  case "varname":
361  $this->setvar->setVarname($value);
362  break;
363  }
364  }
365  }
366  break;
367  case "conditionvar":
368  include_once ("./Services/QTI/classes/class.ilQTIConditionvar.php");
369  $this->conditionvar = new ilQTIConditionvar();
370  break;
371  case "not":
372  if ($this->conditionvar != NULL)
373  {
374  $this->conditionvar->addNot();
375  }
376  break;
377  case "and":
378  if ($this->conditionvar != NULL)
379  {
380  $this->conditionvar->addAnd();
381  }
382  break;
383  case "or":
384  if ($this->conditionvar != NULL)
385  {
386  $this->conditionvar->addOr();
387  }
388  break;
389  case "varequal":
390  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
391  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_EQUAL);
392  if (is_array($a_attribs))
393  {
394  foreach ($a_attribs as $attribute => $value)
395  {
396  switch (strtolower($attribute))
397  {
398  case "case":
399  $this->responsevar->setCase($value);
400  break;
401  case "respident":
402  $this->responsevar->setRespident($value);
403  break;
404  case "index":
405  $this->responsevar->setIndex($value);
406  break;
407  }
408  }
409  }
410  break;
411  case "varlt":
412  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
413  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_LT);
414  if (is_array($a_attribs))
415  {
416  foreach ($a_attribs as $attribute => $value)
417  {
418  switch (strtolower($attribute))
419  {
420  case "respident":
421  $this->responsevar->setRespident($value);
422  break;
423  case "index":
424  $this->responsevar->setIndex($value);
425  break;
426  }
427  }
428  }
429  break;
430  case "varlte":
431  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
432  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_LTE);
433  if (is_array($a_attribs))
434  {
435  foreach ($a_attribs as $attribute => $value)
436  {
437  switch (strtolower($attribute))
438  {
439  case "respident":
440  $this->responsevar->setRespident($value);
441  break;
442  case "index":
443  $this->responsevar->setIndex($value);
444  break;
445  }
446  }
447  }
448  break;
449  case "vargt":
450  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
451  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_GT);
452  if (is_array($a_attribs))
453  {
454  foreach ($a_attribs as $attribute => $value)
455  {
456  switch (strtolower($attribute))
457  {
458  case "respident":
459  $this->responsevar->setRespident($value);
460  break;
461  case "index":
462  $this->responsevar->setIndex($value);
463  break;
464  }
465  }
466  }
467  break;
468  case "vargte":
469  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
470  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_GTE);
471  if (is_array($a_attribs))
472  {
473  foreach ($a_attribs as $attribute => $value)
474  {
475  switch (strtolower($attribute))
476  {
477  case "respident":
478  $this->responsevar->setRespident($value);
479  break;
480  case "index":
481  $this->responsevar->setIndex($value);
482  break;
483  }
484  }
485  }
486  break;
487  case "varsubset":
488  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
489  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_SUBSET);
490  if (is_array($a_attribs))
491  {
492  foreach ($a_attribs as $attribute => $value)
493  {
494  switch (strtolower($attribute))
495  {
496  case "respident":
497  $this->responsevar->setRespident($value);
498  break;
499  case "setmatch":
500  $this->responsevar->setSetmatch($value);
501  break;
502  case "index":
503  $this->responsevar->setIndex($value);
504  break;
505  }
506  }
507  }
508  break;
509  case "varinside":
510  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
511  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_INSIDE);
512  if (is_array($a_attribs))
513  {
514  foreach ($a_attribs as $attribute => $value)
515  {
516  switch (strtolower($attribute))
517  {
518  case "respident":
519  $this->responsevar->setRespident($value);
520  break;
521  case "areatype":
522  $this->responsevar->setAreatype($value);
523  break;
524  case "index":
525  $this->responsevar->setIndex($value);
526  break;
527  }
528  }
529  }
530  break;
531  case "varsubstring":
532  include_once("./Services/QTI/classes/class.ilQTIResponseVar.php");
533  $this->responsevar = new ilQTIResponseVar(RESPONSEVAR_SUBSTRING);
534  if (is_array($a_attribs))
535  {
536  foreach ($a_attribs as $attribute => $value)
537  {
538  switch (strtolower($attribute))
539  {
540  case "case":
541  $this->responsevar->setCase($value);
542  break;
543  case "respident":
544  $this->responsevar->setRespident($value);
545  break;
546  case "index":
547  $this->responsevar->setIndex($value);
548  break;
549  }
550  }
551  }
552  break;
553  case "respcondition":
554  include_once("./Services/QTI/classes/class.ilQTIRespcondition.php");
555  $this->respcondition = new ilQTIRespcondition();
556  if (is_array($a_attribs))
557  {
558  foreach ($a_attribs as $attribute => $value)
559  {
560  switch (strtolower($attribute))
561  {
562  case "continue":
563  $this->respcondition->setContinue($value);
564  break;
565  case "title":
566  $this->respcondition->setTitle($value);
567  break;
568  }
569  }
570  }
571  break;
572  case "outcomes":
573  include_once("./Services/QTI/classes/class.ilQTIOutcomes.php");
574  $this->outcomes = new ilQTIOutcomes();
575  break;
576  case "decvar":
577  include_once("./Services/QTI/classes/class.ilQTIDecvar.php");
578  $this->decvar = new ilQTIDecvar();
579  if (is_array($a_attribs))
580  {
581  foreach ($a_attribs as $attribute => $value)
582  {
583  switch (strtolower($attribute))
584  {
585  case "varname":
586  $this->decvar->setVarname($value);
587  break;
588  case "vartype":
589  $this->decvar->setVartype($value);
590  break;
591  case "defaultval":
592  $this->decvar->setDefaultval($value);
593  break;
594  case "minvalue":
595  $this->decvar->setMinvalue($value);
596  break;
597  case "maxvalue":
598  $this->decvar->setMaxvalue($value);
599  break;
600  case "members":
601  $this->decvar->setMembers($value);
602  break;
603  case "cutvalue":
604  $this->decvar->setCutvalue($value);
605  break;
606  }
607  }
608  }
609  break;
610  case "matimage":
611  include_once("./Services/QTI/classes/class.ilQTIMatimage.php");
612  $this->matimage = new ilQTIMatimage();
613  if (is_array($a_attribs))
614  {
615  foreach ($a_attribs as $attribute => $value)
616  {
617  switch (strtolower($attribute))
618  {
619  case "imagtype":
620  $this->matimage->setImagetype($value);
621  break;
622  case "label":
623  $this->matimage->setLabel($value);
624  break;
625  case "height":
626  $this->matimage->setHeight($value);
627  break;
628  case "width":
629  $this->matimage->setWidth($value);
630  break;
631  case "uri":
632  $this->matimage->setUri($value);
633  break;
634  case "embedded":
635  $this->matimage->setEmbedded($value);
636  break;
637  case "x0":
638  $this->matimage->setX0($value);
639  break;
640  case "y0":
641  $this->matimage->setY0($value);
642  break;
643  case "entityref":
644  $this->matimage->setEntityref($value);
645  break;
646  }
647  }
648  }
649  break;
650  case "material":
651  include_once("./Services/QTI/classes/class.ilQTIMaterial.php");
652  $this->material = new ilQTIMaterial();
653  $this->material->setFlow($this->flow);
654  if (is_array($a_attribs))
655  {
656  foreach ($a_attribs as $attribute => $value)
657  {
658  switch (strtolower($attribute))
659  {
660  case "label":
661  $this->material->setLabel($value);
662  break;
663  }
664  }
665  }
666  break;
667  case "mattext":
668  include_once ("./Services/QTI/classes/class.ilQTIMattext.php");
669  $this->mattext = new ilQTIMattext();
670  if (is_array($a_attribs))
671  {
672  foreach ($a_attribs as $attribute => $value)
673  {
674  switch (strtolower($attribute))
675  {
676  case "texttype":
677  $this->mattext->setTexttype($value);
678  break;
679  case "label":
680  $this->mattext->setLabel($value);
681  break;
682  case "charset":
683  $this->mattext->setCharset($value);
684  break;
685  case "uri":
686  $this->mattext->setUri($value);
687  break;
688  case "xml:space":
689  $this->mattext->setXmlspace($value);
690  break;
691  case "xml:lang":
692  $this->mattext->setXmllang($value);
693  break;
694  case "entityref":
695  $this->mattext->setEntityref($value);
696  break;
697  case "height":
698  $this->mattext->setHeight($value);
699  break;
700  case "width":
701  $this->mattext->setWidth($value);
702  break;
703  case "x0":
704  $this->mattext->setX0($value);
705  break;
706  case "y0":
707  $this->mattext->setY0($value);
708  break;
709  }
710  }
711  }
712  break;
713  case "matapplet":
714  include_once ("./Services/QTI/classes/class.ilQTIMatapplet.php");
715  $this->matapplet = New ilQTIMatapplet();
716  if (is_array($a_attribs))
717  {
718  foreach ($a_attribs as $attribute => $value)
719  {
720  switch (strtolower($attribute))
721  {
722  case "label":
723  $this->matapplet->setLabel($value);
724  break;
725  case "uri":
726  $this->matapplet->setUri($value);
727  break;
728  case "y0":
729  $this->matapplet->setY0($value);
730  break;
731  case "height":
732  $this->matapplet->setHeight($value);
733  break;
734  case "width":
735  $this->matapplet->setWidth($value);
736  break;
737  case "x0":
738  $this->matapplet->setX0($value);
739  break;
740  case "embedded":
741  $this->matapplet->setEmbedded($value);
742  break;
743  case "entityref":
744  $this->matapplet->setEntityref($value);
745  break;
746  }
747  }
748  }
749  break;
750  case "questestinterop":
751  $this->hasRootElement = TRUE;
752  break;
753  case "qticomment":
754  break;
755  case "objectbank":
756  // not implemented yet
757  break;
758  case "section":
759  if ($this->assessment != NULL)
760  {
761  $this->assessment->addSection($this->section);
762  }
763  $this->section = NULL;
764  break;
765  case "presentation":
766  $this->in_presentation = TRUE;
767  include_once ("./Services/QTI/classes/class.ilQTIPresentation.php");
768  $this->presentation = new ilQTIPresentation();
769  break;
770  case "response_label":
771  if ($this->render_type != NULL)
772  {
773  include_once("./Services/QTI/classes/class.ilQTIResponseLabel.php");
774  $this->response_label = new ilQTIResponseLabel();
775  foreach ($a_attribs as $attribute => $value)
776  {
777  switch (strtolower($attribute))
778  {
779  case "rshuffle":
780  $this->response_label->setRshuffle($value);
781  break;
782  case "rarea":
783  $this->response_label->setRarea($value);
784  break;
785  case "rrange":
786  $this->response_label->setRrange($value);
787  break;
788  case "labelrefid":
789  $this->response_label->setLabelrefid($value);
790  break;
791  case "ident":
792  $this->response_label->setIdent($value);
793  break;
794  case "match_group":
795  $this->response_label->setMatchGroup($value);
796  break;
797  case "match_max":
798  $this->response_label->setMatchMax($value);
799  break;
800  }
801  }
802  }
803  break;
804  case "render_choice":
805  if ($this->in_response)
806  {
807  include_once("./Services/QTI/classes/class.ilQTIRenderChoice.php");
808  $this->render_type = new ilQTIRenderChoice();
809  foreach ($a_attribs as $attribute => $value)
810  {
811  switch (strtolower($attribute))
812  {
813  case "shuffle":
814  $this->render_type->setShuffle($value);
815  break;
816  }
817  }
818  }
819  break;
820  case "render_hotspot":
821  if ($this->in_response)
822  {
823  include_once("./Services/QTI/classes/class.ilQTIRenderHotspot.php");
824  $this->render_type = new ilQTIRenderHotspot();
825  foreach ($a_attribs as $attribute => $value)
826  {
827  switch (strtolower($attribute))
828  {
829  case "showdraw":
830  $this->render_type->setShuffle($value);
831  break;
832  case "minnumber":
833  $this->render_type->setMinnumber($value);
834  break;
835  case "maxnumber":
836  $this->render_type->setMaxnumber($value);
837  break;
838  }
839  }
840  }
841  break;
842  case "render_fib":
843  if ($this->in_response)
844  {
845  include_once("./Services/QTI/classes/class.ilQTIRenderFib.php");
846  $this->render_type = new ilQTIRenderFib();
847  foreach ($a_attribs as $attribute => $value)
848  {
849  switch (strtolower($attribute))
850  {
851  case "encoding":
852  $this->render_type->setEncoding($value);
853  break;
854  case "fibtype":
855  $this->render_type->setFibtype($value);
856  break;
857  case "rows":
858  $this->render_type->setRows($value);
859  break;
860  case "maxchars":
861  $this->render_type->setMaxchars($value);
862  break;
863  case "prompt":
864  $this->render_type->setPrompt($value);
865  break;
866  case "columns":
867  $this->render_type->setColumns($value);
868  break;
869  case "charset":
870  $this->render_type->setCharset($value);
871  break;
872  case "maxnumber":
873  $this->render_type->setMaxnumber($value);
874  break;
875  case "minnumber":
876  $this->render_type->setMinnumber($value);
877  break;
878  }
879  }
880  }
881  break;
882  case "response_lid":
883  // Ordering Terms and Definitions or
884  // Ordering Terms and Pictures or
885  // Multiple choice single response or
886  // Multiple choice multiple response
887  case "response_xy":
888  // Imagemap question
889  case "response_str":
890  // Close question
891  case "response_num":
892  case "response_grp":
893  // Matching terms and definitions
894  // Matching terms and images
895  include_once "./Services/QTI/classes/class.ilQTIResponse.php";
896  switch (strtolower($a_name))
897  {
898  case "response_lid":
899  $response_type = RT_RESPONSE_LID;
900  break;
901  case "response_xy":
902  $response_type = RT_RESPONSE_XY;
903  break;
904  case "response_str":
905  $response_type = RT_RESPONSE_STR;
906  break;
907  case "response_num":
908  $response_type = RT_RESPONSE_NUM;
909  break;
910  case "response_grp":
911  $response_type = RT_RESPONSE_GRP;
912  break;
913  }
914  $this->in_response = TRUE;
915  $this->response = new ilQTIResponse($response_type);
916  $this->response->setFlow($this->flow);
917  if (is_array($a_attribs))
918  {
919  foreach ($a_attribs as $attribute => $value)
920  {
921  switch (strtolower($attribute))
922  {
923  case "ident":
924  $this->response->setIdent($value);
925  break;
926  case "rtiming":
927  $this->response->setRTiming($value);
928  break;
929  case "rcardinality":
930  $this->response->setRCardinality($value);
931  break;
932  case "numtype":
933  $this->response->setNumtype($value);
934  break;
935  }
936  }
937  }
938  break;
939  case "item":
940  include_once("./Services/QTI/classes/class.ilQTIItem.php");
941  $this->gap_index = 0;
942  $this->item =& $this->items[array_push($this->items, new ilQTIItem())-1];
943  if (is_array($a_attribs))
944  {
945  foreach ($a_attribs as $attribute => $value)
946  {
947  switch (strtolower($attribute))
948  {
949  case "ident":
950  $this->item->setIdent($value);
951  if (count($this->import_idents) > 0)
952  {
953  if (!in_array($value, $this->import_idents))
954  {
955  $this->do_nothing = TRUE;
956  }
957  }
958  break;
959  case "title":
960  $this->item->setTitle($value);
961  break;
962  case "maxattempts":
963  $this->item->setMaxattempts($value);
964  break;
965  }
966  }
967  }
968  break;
969  case "resprocessing":
970  include_once("./Services/QTI/classes/class.ilQTIResprocessing.php");
971  $this->resprocessing = new ilQTIResprocessing();
972  if (is_array($a_attribs))
973  {
974  foreach ($a_attribs as $attribute => $value)
975  {
976  switch (strtolower($attribute))
977  {
978  case "scoremodel":
979  $this->resprocessing->setScoremodel($value);
980  break;
981  }
982  }
983  }
984  break;
985  }
986  }
987 
991  function handlerEndTag($a_xml_parser,$a_name)
992  {
993  switch ($this->parser_mode)
994  {
995  case IL_MO_PARSE_QTI:
996  $this->handlerParseEndTag($a_xml_parser, $a_name);
997  break;
998  case IL_MO_VERIFY_QTI:
999  $this->handlerVerifyEndTag($a_xml_parser, $a_name);
1000  break;
1001  }
1002  }
1003 
1007  function handlerParseEndTag($a_xml_parser,$a_name)
1008  {
1009  if (($this->do_nothing) && (strcmp(strtolower($a_name), "item") != 0)) return;
1010  switch (strtolower($a_name))
1011  {
1012  case "assessment":
1013  if (is_object($this->tst_object))
1014  {
1015  $this->tst_object->fromXML($this->assessment);
1016  }
1017  $this->in_assessment = FALSE;
1018  break;
1019  case "assessmentcontrol":
1020  $this->assessment->addAssessmentcontrol($this->assessmentcontrol);
1021  $this->assessmentcontrol = NULL;
1022  break;
1023  case "objectives":
1024  if (strcmp(strtolower($this->getParent($a_xml_parser)), "assessment") == 0)
1025  {
1026  $this->assessment->addObjectives($this->objectives);
1027  }
1028  $this->in_objectives = FALSE;
1029  break;
1030  case "itemmetadata":
1031  $this->in_itemmetadata = FALSE;
1032  break;
1033  case "qtimetadatafield":
1034  // handle only specific ILIAS metadata
1035  switch ($this->metadata["label"])
1036  {
1037  case "ILIAS_VERSION":
1038  break;
1039  case "QUESTIONTYPE":
1040  if ($this->item != NULL)
1041  {
1042  $this->item->setQuestiontype($this->metadata["entry"]);
1043  }
1044  break;
1045  case "AUTHOR":
1046  if ($this->item != NULL)
1047  {
1048  $this->item->setAuthor($this->metadata["entry"]);
1049  }
1050  default:
1051  if ($this->item != NULL)
1052  {
1053  $this->item->addMetadata($this->metadata);
1054  }
1055  break;
1056  }
1057  if ($this->in_assessment)
1058  {
1059  $this->assessment->addQtiMetadata($this->metadata);
1060  }
1061  $this->metadata = array("label" => "", "entry" => "");
1062  break;
1063  case "flow":
1064  $this->flow--;
1065  break;
1066  case "flow_mat":
1067  if (count($this->flow_mat))
1068  {
1069  $flow_mat = array_pop($this->flow_mat);
1070  if (count($this->flow_mat))
1071  {
1072  $this->flow_mat[count($this->flow_mat)-1]->addFlow_mat($flow_mat);
1073  }
1074  else if ($this->itemfeedback != NULL)
1075  {
1076  $this->itemfeedback->addFlow_mat($flow_mat);
1077  }
1078  else if ($this->response_label != NULL)
1079  {
1080  $this->response_label->addFlow_mat($flow_mat);
1081  }
1082  }
1083  break;
1084  case "itemfeedback":
1085  if ($this->item != NULL)
1086  {
1087  if ($this->itemfeedback != NULL)
1088  {
1089  $this->item->addItemfeedback($this->itemfeedback);
1090  }
1091  }
1092  $this->itemfeedback = NULL;
1093  break;
1094  case "displayfeedback":
1095  if ($this->respcondition != NULL)
1096  {
1097  if ($this->displayfeedback != NULL)
1098  {
1099  $this->respcondition->addDisplayfeedback($this->displayfeedback);
1100  }
1101  }
1102  $this->displayfeedback = NULL;
1103  break;
1104  case "setvar":
1105  if ($this->respcondition != NULL)
1106  {
1107  if ($this->setvar != NULL)
1108  {
1109  $this->respcondition->addSetvar($this->setvar);
1110  }
1111  }
1112  $this->setvar = NULL;
1113  break;
1114  case "conditionvar":
1115  if ($this->respcondition != NULL)
1116  {
1117  $this->respcondition->setConditionvar($this->conditionvar);
1118  }
1119  $this->conditionvar = NULL;
1120  break;
1121  case "varequal":
1122  case "varlt":
1123  case "varlte":
1124  case "vargt":
1125  case "vargte":
1126  case "varsubset":
1127  case "varinside":
1128  case "varsubstring":
1129  if ($this->conditionvar != NULL)
1130  {
1131  if ($this->responsevar != NULL)
1132  {
1133  $this->conditionvar->addResponseVar($this->responsevar);
1134  }
1135  }
1136  $this->responsevar = NULL;
1137  break;
1138  case "respcondition":
1139  if ($this->resprocessing != NULL)
1140  {
1141  $this->resprocessing->addRespcondition($this->respcondition);
1142  }
1143  $this->respcondition = NULL;
1144  break;
1145  case "outcomes":
1146  if ($this->resprocessing != NULL)
1147  {
1148  $this->resprocessing->setOutcomes($this->outcomes);
1149  }
1150  $this->outcomes = NULL;
1151  break;
1152  case "decvar":
1153  if ($this->outcomes != NULL)
1154  {
1155  $this->outcomes->addDecvar($this->decvar);
1156  }
1157  $this->decvar = NULL;
1158  break;
1159  case "presentation":
1160  $this->in_presentation = FALSE;
1161  if ($this->presentation != NULL)
1162  {
1163  if ($this->item != NULL)
1164  {
1165  $this->item->setPresentation($this->presentation);
1166  }
1167  }
1168  $this->presentation = NULL;
1169  break;
1170  case "response_label":
1171  if ($this->render_type != NULL)
1172  {
1173  $this->render_type->addResponseLabel($this->response_label);
1174  $this->response_label = NULL;
1175  }
1176  break;
1177  case "render_choice":
1178  case "render_hotspot":
1179  case "render_fib":
1180  if ($this->in_response)
1181  {
1182  if ($this->response != NULL)
1183  {
1184  if ($this->render_type != NULL)
1185  {
1186  $this->response->setRenderType($this->render_type);
1187  $this->render_type = NULL;
1188  }
1189  }
1190  }
1191  break;
1192  case "response_lid":
1193  case "response_xy":
1194  case "response_str":
1195  case "response_num":
1196  case "response_grp":
1197  $this->gap_index++;
1198  if ($this->presentation != NULL)
1199  {
1200  if ($this->response != NULL)
1201  {
1202  $this->presentation->addResponse($this->response);
1203  if ($this->item != NULL)
1204  {
1205  $this->item->addPresentationitem($this->response);
1206  }
1207  }
1208  }
1209  $this->response = NULL;
1210  $this->in_response = FALSE;
1211  break;
1212  case "item":
1213  if ($this->do_nothing)
1214  {
1215  $this->do_nothing = FALSE;
1216  return;
1217  }
1218  if (strlen($this->item->getQuestionType()))
1219  {
1220  // this is an ILIAS QTI question
1221  }
1222  else
1223  {
1224  // this is a QTI question which wasn't generated by ILIAS
1225  }
1226  global $ilDB;
1227  global $ilUser;
1228  // save the item directly to save memory
1229  // the database id's of the created items are exported. if the import fails
1230  // ILIAS can delete the already imported items
1231 
1232  // problems: the object id of the parent questionpool is not yet known. must be set later
1233  // the complete flag must be calculated?
1234  $qt = $this->item->determineQuestionType();
1235  $presentation = $this->item->getPresentation();
1236 
1237  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1239  $question = new $qt();
1240  $question->fromXML($this->item, $this->qpl_id, $this->tst_id, $this->tst_object, $this->question_counter, $this->import_mapping);
1241  break;
1242  case "material":
1243  if ($this->material)
1244  {
1245  $mat = $this->material->getMaterial(0);
1246  if ((strcmp($mat["type"], "mattext") == 0) && (strcmp($mat["material"]->getLabel(), "suggested_solution") == 0))
1247  {
1248  $this->item->addSuggestedSolution($mat["material"], $this->gap_index);
1249  }
1250  if ($this->in_objectives)
1251  {
1252  $this->objectives->addMaterial($this->material);
1253  }
1254  else if (($this->render_type != NULL) && (strcmp(strtolower($this->getParent($a_xml_parser)), "render_hotspot") == 0))
1255  {
1256  $this->render_type->addMaterial($this->material);
1257  }
1258  else if (count($this->flow_mat) && (strcmp(strtolower($this->getParent($a_xml_parser)), "flow_mat") == 0))
1259  {
1260  $this->flow_mat[count($this->flow_mat)-1]->addMaterial($this->material);
1261  }
1262  else if ($this->itemfeedback != NULL)
1263  {
1264  $this->itemfeedback->addMaterial($this->material);
1265  }
1266  else if ($this->response_label != NULL)
1267  {
1268  $this->response_label->addMaterial($this->material);
1269  }
1270  else if ($this->response != NULL)
1271  {
1272  if ($this->response->hasRendering())
1273  {
1274  $this->response->setMaterial2($this->material);
1275  }
1276  else
1277  {
1278  $this->response->setMaterial1($this->material);
1279  }
1280  }
1281  elseif (($this->in_presentation) && (!$this->in_response))
1282  {
1283  if (!is_object($this->item->getQuestiontext()))
1284  {
1285  $this->item->setQuestiontext($this->material);
1286  }
1287  $this->presentation->addMaterial($this->material);
1288  }
1289  else if ($this->presentation != NULL)
1290  {
1291  $this->presentation->addMaterial($this->material);
1292  if ($this->item != NULL)
1293  {
1294  $this->item->addPresentationitem($this->material);
1295  }
1296  }
1297  }
1298  $this->material = NULL;
1299  break;
1300  case "matimage";
1301  if ($this->material != NULL)
1302  {
1303  if ($this->matimage != NULL)
1304  {
1305  $this->material->addMatimage($this->matimage);
1306  }
1307  }
1308  $this->matimage = NULL;
1309  break;
1310  case "resprocessing":
1311  if ($this->item != NULL)
1312  {
1313  $this->item->addResprocessing($this->resprocessing);
1314  }
1315  $this->resprocessing = NULL;
1316  break;
1317  case "mattext":
1318  if ($this->material != NULL)
1319  {
1320  $this->material->addMattext($this->mattext);
1321  }
1322  $this->mattext = NULL;
1323  break;
1324  case "matapplet":
1325  if ($this->material != NULL)
1326  {
1327  $this->material->addMatapplet($this->matapplet);
1328  }
1329  $this->matapplet = NULL;
1330  break;
1331  }
1332  $this->depth[$a_xml_parser]--;
1333  }
1334 
1338  function handlerCharacterData($a_xml_parser,$a_data)
1339  {
1340  switch ($this->parser_mode)
1341  {
1342  case IL_MO_PARSE_QTI:
1343  $this->handlerParseCharacterData($a_xml_parser, $a_data);
1344  break;
1345  case IL_MO_VERIFY_QTI:
1346  $this->handlerVerifyCharacterData($a_xml_parser, $a_data);
1347  break;
1348  }
1349  }
1350 
1354  function handlerParseCharacterData($a_xml_parser,$a_data)
1355  {
1356  if ($this->do_nothing) return;
1357  $this->characterbuffer .= $a_data;
1358  $a_data = $this->characterbuffer;
1359  switch ($this->qti_element)
1360  {
1361  case "fieldlabel":
1362  $this->metadata["label"] = $a_data;
1363  break;
1364  case "fieldentry":
1365  $this->metadata["entry"] = $a_data;
1366  break;
1367  case "response_label":
1368  if ($this->response_label != NULL)
1369  {
1370  $this->response_label->setContent($a_data);
1371  }
1372  break;
1373  case "setvar":
1374  if ($this->setvar != NULL)
1375  {
1376  $this->setvar->setContent($a_data);
1377  }
1378  break;
1379  case "displayfeedback":
1380  if ($this->displayfeedback != NULL)
1381  {
1382  $this->displayfeedback->setContent($a_data);
1383  }
1384  break;
1385  case "varequal":
1386  case "varlt":
1387  case "varlte":
1388  case "vargt":
1389  case "vargte":
1390  case "varsubset":
1391  case "varinside":
1392  case "varsubstring":
1393  if ($this->responsevar != NULL)
1394  {
1395  $this->responsevar->setContent($a_data);
1396  }
1397  break;
1398  case "decvar":
1399  if (strlen($a_data))
1400  {
1401  if ($this->decvar != NULL)
1402  {
1403  $this->decvar->setContent($a_data);
1404  }
1405  }
1406  break;
1407  case "mattext":
1408  if ($this->mattext != NULL)
1409  {
1410  $this->mattext->setContent($a_data);
1411  }
1412  break;
1413  case "matapplet":
1414  if ($this->matapplet != NULL)
1415  {
1416  $this->matapplet->setContent($a_data);
1417  }
1418  break;
1419  case "matimage":
1420  if ($this->matimage != NULL)
1421  {
1422  $this->matimage->setContent($a_data);
1423  }
1424  break;
1425  case "duration":
1426  switch ($this->getParent($a_xml_parser))
1427  {
1428  case "assessment":
1429  // to be done
1430  break;
1431  case "section":
1432  // to be done
1433  break;
1434  case "item":
1435  $this->item->setDuration($a_data);
1436  break;
1437  }
1438  break;
1439  case "qticomment":
1440  switch ($this->getParent($a_xml_parser))
1441  {
1442  case "item":
1443  $this->item->setComment($a_data);
1444  break;
1445  case "assessment":
1446  $this->assessment->setComment($a_data);
1447  break;
1448  default:
1449  break;
1450  }
1451  break;
1452  }
1453  $this->sametag = TRUE;
1454  }
1455 
1459  function handlerVerifyBeginTag($a_xml_parser,$a_name,$a_attribs)
1460  {
1461  switch (strtolower($a_name))
1462  {
1463  case "questestinterop":
1464  $this->verifyroot = true;
1465  break;
1466  case "qtimetadatafield":
1467  $this->verifymetadatafield = 1;
1468  break;
1469  case "fieldlabel":
1470  $this->verifyfieldlabeltext = "";
1471  if ($this->verifymetadatafield == 1) $this->verifyfieldlabel = 1;
1472  break;
1473  case "fieldentry":
1474  $this->verifyfieldentrytext = "";
1475  if ($this->verifymetadatafield == 1) $this->verifyfieldentry = 1;
1476  break;
1477  case "item":
1478  $title = "";
1479  if (is_array($a_attribs))
1480  {
1481  foreach ($a_attribs as $attribute => $value)
1482  {
1483  switch (strtolower($attribute))
1484  {
1485  case "title":
1486  $title = $value;
1487  break;
1488  }
1489  }
1490  }
1491  array_push($this->founditems, array("title" => "$title", "type" => "", "ident" => $a_attribs["ident"]));
1492  break;
1493  case "response_lid":
1494  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1495  {
1496  // test for non ILIAS generated question types
1497  if (is_array($a_attribs))
1498  {
1499  foreach ($a_attribs as $attribute => $value)
1500  {
1501  switch (strtolower($attribute))
1502  {
1503  case "rcardinality":
1504  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1505  switch (strtolower($value))
1506  {
1507  case "single":
1508  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_SR;
1509  break;
1510  case "multiple":
1511  $this->founditems[count($this->founditems)-1]["type"] = QT_MULTIPLE_CHOICE_MR;
1512  break;
1513  case "ordered":
1514  $this->founditems[count($this->founditems)-1]["type"] = QT_ORDERING;
1515  break;
1516  }
1517  break;
1518  }
1519  }
1520  }
1521  }
1522  break;
1523  case "response_str":
1524  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1525  {
1526  // test for non ILIAS generated question types
1527  if (is_array($a_attribs))
1528  {
1529  foreach ($a_attribs as $attribute => $value)
1530  {
1531  switch (strtolower($attribute))
1532  {
1533  case "rcardinality":
1534  include_once "./Services/QTI/classes/class.ilQTIItem.php";
1535  switch (strtolower($value))
1536  {
1537  case "single":
1538  $this->founditems[count($this->founditems)-1]["type"] = QT_CLOZE;
1539  break;
1540  case "ordered":
1541  $this->founditems[count($this->founditems)-1]["type"] = QT_TEXT;
1542  break;
1543  }
1544  break;
1545  }
1546  }
1547  }
1548  }
1549  break;
1550  case "response_xy":
1551  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1552  {
1553  $this->founditems[count($this->founditems)-1]["type"] = QT_IMAGEMAP;
1554  }
1555  break;
1556  case "response_num":
1557  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1558  {
1559  $this->founditems[count($this->founditems)-1]["type"] = QT_NUMERIC;
1560  }
1561  break;
1562  case "response_grp":
1563  if (strlen($this->founditems[count($this->founditems)-1]["type"]) == 0)
1564  {
1565  $this->founditems[count($this->founditems)-1]["type"] = QT_MATCHING;
1566  }
1567  break;
1568  case "qticomment":
1569  // check for "old" ILIAS qti format (not well formed)
1570  $this->verifyqticomment = 1;
1571  break;
1572  case "presentation":
1573  if (is_array($a_attribs))
1574  {
1575  foreach ($a_attribs as $attribute => $value)
1576  {
1577  switch (strtolower($attribute))
1578  {
1579  case "label":
1580  $this->founditems[count($this->founditems)-1]["title"] = $value;
1581  break;
1582  }
1583  }
1584  }
1585  break;
1586  }
1587  }
1588 
1592  function handlerVerifyEndTag($a_xml_parser,$a_name)
1593  {
1594  switch (strtolower($a_name))
1595  {
1596  case "qticomment":
1597  // check for "old" ILIAS qti format (not well formed)
1598  $this->verifyqticomment = 0;
1599  break;
1600  case "qtimetadatafield":
1601  $this->verifymetadatafield = 0;
1602  if (strcmp($this->verifyfieldlabeltext, "QUESTIONTYPE") == 0)
1603  {
1604  $this->founditems[count($this->founditems)-1]["type"] = $this->verifyfieldentrytext;
1605  }
1606  break;
1607  case "fieldlabel":
1608  $this->verifyfieldlabel = 0;
1609  break;
1610  case "fieldentry":
1611  $this->verifyfieldentry = 0;
1612  break;
1613  }
1614  }
1615 
1619  function handlerVerifyCharacterData($a_xml_parser,$a_data)
1620  {
1621  if ($this->verifyqticomment == 1)
1622  {
1623  if (preg_match("/Questiontype\=(.*)/", $a_data, $matches))
1624  {
1625  if (count($this->founditems))
1626  {
1627  $this->founditems[count($this->founditems)-1]["type"] = $matches[1];
1628  }
1629  }
1630  }
1631  else if ($this->verifyfieldlabel == 1)
1632  {
1633  $this->verifyfieldlabeltext = $a_data;
1634  }
1635  else if ($this->verifyfieldentry == 1)
1636  {
1637  $this->verifyfieldentrytext = $a_data;
1638  }
1639  }
1640 
1641  function &getFoundItems()
1642  {
1643  return $this->founditems;
1644  }
1645 
1650  function getImportMapping()
1651  {
1652  if (!is_array($this->import_mapping))
1653  {
1654  return array();
1655  }
1656  else
1657  {
1658  return $this->import_mapping;
1659  }
1660  }
1661 
1662 }
1663 ?>