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