/** * @dataProvider getXsdLocationProvider * * @param string $file * @param string $namespaceUri * @param boolean|string $expectedLocation */ public function testGetXsdLocation($file, $namespaceUri, $expectedLocation) { $document = new DOMDocument('1.0', 'UTF-8'); $document->load($file); $location = Utils::getXsdLocation($document, $namespaceUri); $this->assertSame($expectedLocation, $location); }
protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '') { try { $dom = $component->getXml(); $node = $fragment->ownerDocument->importNode($dom->documentElement, true); $node = Utils::anonimizeElement($node); $node->setAttribute('xmlns', 'http://www.w3.org/1998/Math/MathML'); $fragment->appendChild($node); } catch (RuntimeException $e) { $msg = "An error occured while rendering the XML content of the 'MathML' external component."; throw new RenderingException($msg, RenderingException::UNKNOWN, $e); } }
/** * Marshall a CustomInteraction object into a DOMElement object. * * @param \qtism\data\QtiComponent $component A CustomInteraction object. * @return \DOMElement The according DOMElement object. */ protected function marshall(QtiComponent $component) { $element = static::getDOMCradle()->createElement('customInteraction'); $this->fillElement($element, $component); self::setDOMElementAttribute($element, 'responseIdentifier', $component->getResponseIdentifier()); if ($component->hasXmlBase() === true) { self::setXmlBase($element, $component->getXmlBase()); } $xml = $component->getXml(); Utils::importChildNodes($xml->documentElement, $element); Utils::importAttributes($xml->documentElement, $element); return $element; }
/** * @see \qtism\runtime\rendering\markup\xhtml\ExternalQtiComponentRenderer::appendChildren() */ protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '') { try { $dom = $component->getXml(); $node = $fragment->ownerDocument->importNode($dom->documentElement, true); $nodeNamespaceUri = $node->namespaceURI; $node = Utils::anonimizeElement($node); if ($this->mustNamespaceOutput() === true) { $node->setAttribute('xmlns', $nodeNamespaceUri); } $fragment->appendChild($node); } catch (RuntimeException $e) { $msg = "An error occured while rendering the XML content of the 'MathML' external component."; throw new RenderingException($msg, RenderingException::UNKNOWN, $e); } }
/** * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren() */ protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '') { parent::appendChildren($fragment, $component, $base); // Retrieve the two rendered simpleMatchSets and shuffle if needed. $currentSet = 0; $choiceElts = array(); $simpleMatchSetElts = array(); for ($i = 0; $i < $fragment->firstChild->childNodes->length; $i++) { $n = $fragment->firstChild->childNodes->item($i); if (Utils::hasClass($n, 'qti-simpleMatchSet') === true) { $simpleMatchSetElts[] = $n; $sets = $component->getSimpleMatchSets(); if ($this->getRenderingEngine()->getShufflingPolicy() === AbstractMarkupRenderingEngine::CONTEXT_AWARE && $component->mustShuffle()) { Utils::shuffle($n, new ShufflableCollection($sets[$currentSet]->getSimpleAssociableChoices()->getArrayCopy())); } // Retrieve the two content of the two simpleMatchSets, separately. $choiceElts[] = Marshaller::getChildElementsByTagName($n, 'li'); $currentSet++; } } // simpleMatchSet class cannot be rendered into a table :/ foreach ($simpleMatchSetElts as $sms) { $fragment->firstChild->removeChild($sms); } $table = $fragment->ownerDocument->createElement('table'); $fragment->firstChild->appendChild($table); // Build the table header. $tr = $fragment->ownerDocument->createElement('tr'); $table->appendChild($tr); // Empty upper left cell. $tr->appendChild($fragment->ownerDocument->createElement('th')); $ifVerticalStatementsStorage = array(); for ($i = 0; $i < count($choiceElts[1]); $i++) { $ifStatements = Utils::extractStatements($choiceElts[1][$i], Utils::EXTRACT_IF); $incStatements = Utils::extractStatements($choiceElts[1][$i], Utils::EXTRACT_INCLUDE); if (empty($incStatements) === false) { $tr->appendChild($incStatements[0]); } if (empty($ifStatements) === false) { $ifVerticalStatementsStorage[$i] = $ifStatements; $tr->appendChild($ifStatements[0]); } $th = XmlUtils::changeElementName($choiceElts[1][$i], 'th'); $tr->appendChild($th); if (empty($incStatements) === false) { $th->parentNode->insertBefore($incStatements[1], $th->nextSibling); } if (empty($ifStatements) === false) { $th->parentNode->insertBefore($ifStatements[1], $th->nextSibling); } } // Build all remaining rows. for ($i = 0; $i < count($choiceElts[0]); $i++) { $tr = $fragment->ownerDocument->createElement('tr'); $ifStatements = Utils::extractStatements($choiceElts[0][$i], Utils::EXTRACT_IF); $incStatements = Utils::extractStatements($choiceElts[0][$i], Utils::EXTRACT_INCLUDE); $th = XmlUtils::changeElementName($choiceElts[0][$i], 'th'); $tr->appendChild($th); $table->appendChild($tr); if (empty($incStatements) === false) { $tr->parentNode->insertBefore($incStatements[0], $tr); } if (empty($ifStatements) === false) { $tr->parentNode->insertBefore($ifStatements[0], $tr); } for ($j = 0; $j < count($choiceElts[1]); $j++) { $input = $fragment->ownerDocument->createElement('input'); $input->setAttribute('type', 'checkbox'); $td = $fragment->ownerDocument->createElement('td'); $td->appendChild($input); $tr->appendChild($td); if (isset($ifVerticalStatementsStorage[$j])) { $td->parentNode->insertBefore($ifVerticalStatementsStorage[$j][0]->cloneNode(), $td); $td->parentNode->insertBefore($ifVerticalStatementsStorage[$j][1]->cloneNode(), $td->nextSibling); } } if (empty($incStatements) === false && isset($td)) { $tr->parentNode->insertBefore($incStatements[1], $tr->nextSibling); } if (empty($ifStatements) === false && isset($td)) { $tr->parentNode->insertBefore($ifStatements[1], $tr->nextSibling); } } }
/** * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::marshallChildrenKnown() */ protected function marshallChildrenKnown(QtiComponent $component, array $elements) { $element = self::getDOMCradle()->createElement($component->getQtiClassName()); foreach ($elements as $elt) { $element->appendChild($elt); } if ($component instanceof CustomOperator) { if ($component->hasClass() === true) { self::setDOMElementAttribute($element, 'class', $component->getClass()); } if ($component->hasDefinition() === true) { self::setDOMElementAttribute($element, 'definition', $component->getDefinition()); } // Now, we have to extract the LAX content of the custom operator and put it into // what we are putting out. (It is possible to have no LAX content at all, it is not mandatory). $xml = $component->getXml(); $operatorElt = $xml->documentElement->cloneNode(true); $qtiOperatorElts = self::getChildElementsByTagName($operatorElt, array_merge(self::getOperators(), self::getExpressions())); foreach ($qtiOperatorElts as $qtiOperatorElt) { $operatorElt->removeChild($qtiOperatorElt); } Utils::importChildNodes($operatorElt, $element); Utils::importAttributes($operatorElt, $element); } return $element; }
/** * Run the rendering behaviour related to the "XHTML" flavour. * * @param \qtism\data\storage\xml\XmlDocument $doc The QTI XML document to be rendered. * @param \qtism\runtime\rendering\markup\xhtml\XhtmlRenderingEngine $renderer * @return string The raw rendering data. */ private function runXhtml(XmlDocument $doc, XhtmlRenderingEngine $renderer) { $arguments = $this->getArguments(); $profile = $arguments['flavour']; $xml = $renderer->render($doc->getDocumentComponent()); $header = ''; $footer = ''; $indent = ''; $nl = ''; if ($arguments['format'] === true) { $xml->formatOutput = true; $indent .= " "; $nl .= "\n"; } if ($arguments['document'] === true) { $rootComponent = $doc->getDocumentComponent(); $title = ''; if ($rootComponent->getQtiClassName() === 'assessmentItem') { $title = XmlUtils::escapeXmlSpecialChars($rootComponent->getTitle()); } $header .= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; $header .= "<html>{$nl}"; $header .= "{$indent}<head>{$nl}"; $header .= "{$indent}{$indent}<meta charset=\"utf-8\">{$nl}"; if (empty($title) !== false) { $header .= "{$indent}{$indent}<title>" . $title . "</title>{$nl}"; } $header .= "{$indent}{$indent}" . $renderer->getStylesheets()->ownerDocument->saveXML($renderer->getStylesheets()); $header .= "{$indent}</head>{$nl}"; $header .= "{$indent}<body>{$nl}"; $footer = "{$indent}</body>{$nl}"; $footer .= "</html>\n"; } $body = $xml->saveXml($xml->documentElement) . "{$nl}"; // Indent body... $indentBody = ''; if ($arguments['document'] === null) { $indent = ''; } foreach (preg_split('/\\n|\\r/u', $body, -1, PREG_SPLIT_NO_EMPTY) as $bodyLine) { // do stuff with $line $indentBody .= "{$indent}{$indent}{$bodyLine}{$nl}"; } $body = $indentBody; return "{$header}{$indentBody}{$footer}"; }
protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '') { parent::appendChildren($fragment, $component, $base); // Retrieve the two rendered simpleMatchSets and shuffle if needed. $currentSet = 0; $choiceElts = array(); $simpleMatchSetElts = array(); for ($i = 0; $i < $fragment->firstChild->childNodes->length; $i++) { $n = $fragment->firstChild->childNodes->item($i); if (Utils::hasClass($n, 'qti-simpleMatchSet') === true) { $simpleMatchSetElts[] = $n; $sets = $component->getSimpleMatchSets(); if ($this->getRenderingEngine()->mustShuffle() === true) { Utils::shuffle($n, new ShufflableCollection($sets[$currentSet]->getSimpleAssociableChoices()->getArrayCopy())); } // Retrieve the two content of the two simpleMatchSets, separately. $choiceElts[] = Marshaller::getChildElementsByTagName($n, 'div'); $currentSet++; } } // simpleMatchSet class cannot be rendered into a table :/ foreach ($simpleMatchSetElts as $sms) { $fragment->firstChild->removeChild($sms); } $table = $fragment->ownerDocument->createElement('table'); $fragment->firstChild->appendChild($table); // Build the table header. $tr = $fragment->ownerDocument->createElement('tr'); $table->appendChild($tr); // Empty upper left cell. $tr->appendChild($fragment->ownerDocument->createElement('th')); for ($i = 0; $i < count($choiceElts[1]); $i++) { $tr->appendChild(XmlUtils::changeElementName($choiceElts[1][$i], 'th')); } // Build all remaining rows. for ($i = 0; $i < count($choiceElts[0]); $i++) { $tr = $fragment->ownerDocument->createElement('tr'); $tr->appendChild(XmlUtils::changeElementName($choiceElts[0][$i], 'th')); $table->appendChild($tr); for ($j = 0; $j < count($choiceElts[1]); $j++) { $input = $fragment->ownerDocument->createElement('input'); $input->setAttribute('type', 'checkbox'); $td = $fragment->ownerDocument->createElement('td'); $td->appendChild($input); $tr->appendChild($td); } } }
/** * Infer the QTI version of the document from its XML definition. * * @return boolean|string false if cannot be infered otherwise a semantic version of the QTI version with major, minor and patch versions e.g. '2.1.0'. */ protected function inferVersion() { return XmlUtils::inferVersion($this->getDomDocument()); }
/** * * @param string $originalXmlString * @param string $expectedXmlString * @dataProvider anonimizeElementProvider */ public function testAnonimizeElement($originalXmlString, $expectedXmlString) { $elt = $this->createDOMElement($originalXmlString); $newElt = Utils::anonimizeElement($elt); $this->assertEquals($expectedXmlString, $newElt->ownerDocument->saveXML($newElt)); }
public function schemaValidate($filename = '') { if (empty($filename)) { $filename = XmlUtils::getSchemaLocation($this->getVersion()); } if (is_readable($filename)) { $oldErrorConfig = libxml_use_internal_errors(true); $doc = $this->getDomDocument(); if (@$doc->schemaValidate($filename) === false) { $libXmlErrors = libxml_get_errors(); $formattedErrors = self::formatLibXmlErrors($libXmlErrors); libxml_clear_errors(); libxml_use_internal_errors($oldErrorConfig); $msg = "The document could not be validated with schema '{$filename}':\n{$formattedErrors}"; throw new XmlStorageException($msg, null, new LibXmlErrorCollection($libXmlErrors)); } } else { $msg = "Schema '{$filename}' cannot be read. Does this file exist? Is it readable?"; throw new InvalidArgumentException($msg); } }