/** * Build a QTI_Item from a DOMElement, the root tag of which is root assessmentItem * * @param DOMElement $data * @return oat\taoQtiItem\model\qti\Item * @throws oat\taoQtiItem\model\qti\exception\ParsingException */ protected function buildItem(DOMElement $data) { //check on the root tag. $itemId = (string) $data->getAttribute('identifier'); common_Logger::i('Started parsing of QTI item' . (isset($itemId) ? ' ' . $itemId : ''), array('TAOITEMS')); //create the item instance $this->item = new Item($this->extractAttributes($data)); foreach ($this->queryXPath('namespace::*') as $node) { $name = preg_replace('/xmlns(:)?/', '', $node->nodeName); $this->item->addNamespace($name, $node->nodeValue); } $nsQti = $this->item->getNamespace('http://www.imsglobal.org/xsd/imsqti_v2p1'); $this->qtiPrefix = $nsQti ? $nsQti . ':' : ''; $styleSheetNodes = $this->queryXPath("*[name(.) = 'stylesheet']", $data); foreach ($styleSheetNodes as $styleSheetNode) { $styleSheet = $this->buildStylesheet($styleSheetNode); $this->item->addStylesheet($styleSheet); } //extract the responses $responseNodes = $this->queryXPath("*[name(.) = 'responseDeclaration']", $data); foreach ($responseNodes as $responseNode) { $response = $this->buildResponseDeclaration($responseNode); if (!is_null($response)) { $this->item->addResponse($response); } } //extract outcome variables $outcomes = array(); $outComeNodes = $this->queryXPath("*[name(.) = 'outcomeDeclaration']", $data); foreach ($outComeNodes as $outComeNode) { $outcome = $this->buildOutcomeDeclaration($outComeNode); if (!is_null($outcome)) { $outcomes[] = $outcome; } } if (count($outcomes) > 0) { $this->item->setOutcomes($outcomes); } //extract modal feedbacks $feedbackNodes = $this->queryXPath("*[name(.) = 'modalFeedback']", $data); foreach ($feedbackNodes as $feedbackNode) { $modalFeedback = $this->buildFeedback($feedbackNode); if (!is_null($modalFeedback)) { $this->item->addModalFeedback($modalFeedback); } } //extract the item structure to separate the structural/style content to the item content $itemBodies = $this->queryXPath("*[name(.) = 'itemBody']", $data); // array with 1 or zero bodies if ($itemBodies === false) { $errors = libxml_get_errors(); if (count($errors) > 0) { $error = array_shift($errors); $errormsg = $error->message; } else { $errormsg = "without errormessage"; } throw new ParsingException('XML error(' . $errormsg . ') on itemBody read' . (isset($itemId) ? ' for item ' . $itemId : '')); } elseif ($itemBodies->length) { $this->parseContainerItemBody($itemBodies->item(0), $this->item->getBody()); } //warning: extract the response processing at the latest to make oat\taoQtiItem\model\qti\response\TemplatesDriven::takeOverFrom() work $rpNodes = $this->queryXPath("*[name(.) = 'responseProcessing']", $data); if ($rpNodes->length === 0) { common_Logger::i('No responseProcessing found for QTI Item, setting empty custom', array('QTI', 'TAOITEMS')); $customrp = new Custom(array(), '<responseProcessing/>'); $this->item->setResponseProcessing($customrp); } else { $rpNode = $rpNodes->item(0); //the node should be alone $rProcessing = $this->buildResponseProcessing($rpNode, $this->item); if (!is_null($rProcessing)) { $this->item->setResponseProcessing($rProcessing); } } return $this->item; }