Process Matching Questions
@param array $xml the xml tree
@param array $questions the questions already parsed
551777
public function process_matching($xml, &$questions) {
        if ($this->getpath($xml, array('POOL', '#', 'QUESTION_MATCH'), false, false)) {
            $matchquestions = $this->getpath($xml,
                    array('POOL', '#', 'QUESTION_MATCH'), false, false);
        } else {
            return;
        }
        // Blackboard questions can't be imported in core Moodle without a loss in data,
        // as core match question don't allow HTML in subanswers. The contributed ddmatch
        // question type support HTML in subanswers.
        // The ddmatch question type is not part of core, so we need to check if it is defined.
        $ddmatchisinstalled = question_bank::is_qtype_installed('ddmatch');

        foreach ($matchquestions as $thisquestion) {

            $question = $this->process_common($thisquestion);
            if ($ddmatchisinstalled) {
                $question->qtype = 'ddmatch';
            } else {
                $question->qtype = 'match';
            }

            $correctfeedback = $this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'FEEDBACK_WHEN_CORRECT', 0, '#'),
                    '', true);
            $incorrectfeedback = $this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'FEEDBACK_WHEN_INCORRECT', 0, '#'),
                    '', true);
            $question->correctfeedback = $this->cleaned_text_field($correctfeedback);
            // As there is no partially correct feedback we use incorrect one.
            $question->partiallycorrectfeedback = $this->cleaned_text_field($incorrectfeedback);
            $question->incorrectfeedback = $this->cleaned_text_field($incorrectfeedback);

            $choices = $this->getpath($thisquestion,
                    array('#', 'CHOICE'), false, false); // Blackboard "choices" are Moodle subanswers.
            $answers = $this->getpath($thisquestion,
                    array('#', 'ANSWER'), false, false); // Blackboard "answers" are Moodle subquestions.
            $correctanswers = $this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'CORRECTANSWER'), false, false); // Mapping between choices and answers.
            $mappings = array();
            foreach ($correctanswers as $correctanswer) {
                if ($correctanswer) {
                    $correctchoiceid = $this->getpath($correctanswer,
                                array('@', 'choice_id'), '', true);
                    $correctanswerid = $this->getpath($correctanswer,
                            array('@', 'answer_id'),
                            '', true);
                    $mappings[$correctanswerid] = $correctchoiceid;
                }
            }

            foreach ($choices as $choice) {
                if ($ddmatchisinstalled) {
                    $choicetext = $this->cleaned_text_field($this->getpath($choice,
                            array('#', 'TEXT', 0, '#'), '', true));
                } else {
                    $choicetext = trim(strip_tags($this->getpath($choice,
                            array('#', 'TEXT', 0, '#'), '', true)));
                }

                if ($choicetext != '') { // Only import non empty subanswers.
                    $subquestion = '';
                    $choiceid = $this->getpath($choice,
                            array('@', 'id'), '', true);
                    $fiber = array_search($choiceid, $mappings);
                    $fiber = array_keys ($mappings, $choiceid);
                    foreach ($fiber as $correctanswerid) {
                        // We have found a correspondance for this choice so we need to take the associated answer.
                        foreach ($answers as $answer) {
                            $currentanswerid = $this->getpath($answer,
                                    array('@', 'id'), '', true);
                            if (strcmp ($currentanswerid, $correctanswerid) == 0) {
                                $subquestion = $this->getpath($answer,
                                        array('#', 'TEXT', 0, '#'), '', true);
                                break;
                            }
                        }
                        $question->subquestions[] = $this->cleaned_text_field($subquestion);
                        $question->subanswers[] = $choicetext;
                    }

                    if ($subquestion == '') { // Then in this case, $choice is a distractor.
                        $question->subquestions[] = $this->text_field('');
                        $question->subanswers[] = $choicetext;
                    }
                }
            }

            // Verify that this matching question has enough subquestions and subanswers.
            $subquestioncount = 0;
            $subanswercount = 0;
            $subanswers = $question->subanswers;
            foreach ($question->subquestions as $key => $subquestion) {
                $subquestion = $subquestion['text'];
                $subanswer = $subanswers[$key];
                if ($subquestion != '') {
                    $subquestioncount++;
                }
                $subanswercount++;
            }
            if ($subquestioncount < 2 || $subanswercount < 3) {
                    $this->error(get_string('notenoughtsubans', 'qformat_blackboard_six', $question->questiontext));
            } else {
                $questions[] = $question;
            }

        }
    }
1303955
public function process_ma($xml, &$questions) {
        if ($this->getpath($xml, array('POOL', '#', 'QUESTION_MULTIPLEANSWER'), false, false)) {
            $maquestions = $this->getpath($xml,
                    array('POOL', '#', 'QUESTION_MULTIPLEANSWER'), false, false);
        } else {
            return;
        }

        foreach ($maquestions as $thisquestion) {
            $question = $this->process_common($thisquestion);

            $correctfeedback = $this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'FEEDBACK_WHEN_CORRECT', 0, '#'),
                    '', true);
            $incorrectfeedback = $this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'FEEDBACK_WHEN_INCORRECT', 0, '#'),
                    '', true);
            $question->correctfeedback = $this->cleaned_text_field($correctfeedback);
            // As there is no partially correct feedback we use incorrect one.
            $question->partiallycorrectfeedback = $this->cleaned_text_field($incorrectfeedback);
            $question->incorrectfeedback = $this->cleaned_text_field($incorrectfeedback);

            $question->qtype = 'multichoice';
            $question->defaultmark = 1;
            $question->single = 0; // More than one answers allowed.

            $choices = $this->getpath($thisquestion, array('#', 'ANSWER'), false, false);
            $correctanswerids = array();
            foreach ($this->getpath($thisquestion,
                    array('#', 'GRADABLE', 0, '#', 'CORRECTANSWER'), false, false) as $correctanswer) {
                if ($correctanswer) {
                    $correctanswerids[] = $this->getpath($correctanswer,
                            array('@', 'answer_id'),
                            '', true);
                }
            }
            $fraction = 1 / count($correctanswerids);

            foreach ($choices as $choice) {
                $choicetext = $this->getpath($choice, array('#', 'TEXT', 0, '#'), '', true);
                // Put this choice in the question object.
                $question->answer[] = $this->cleaned_text_field($choicetext);

                $choiceid = $this->getpath($choice, array('@', 'id'), '', true);

                $iscorrect = in_array($choiceid, $correctanswerids);

                if ($iscorrect) {
                    $question->fraction[] = $fraction;
                } else {
                    $question->fraction[] = 0;
                }
                // There is never feedback specific to each choice.
                $question->feedback[] = $this->text_field('');
            }
            $questions[] = $question;
        }
    }
686120
public function addNodes($nodes, $attributes = [])
    {
        foreach ($nodes as $pattern => $answers) {
            $this->addNode($pattern, $answers, $attributes);
        }
    }
654951
public function process(\DOMDocument $xml)
    {
        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query(
            '/project/file/class/docblock/tag[@name="method"]'
        );

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $class = $node->parentNode->parentNode;

            $method = new \DOMElement('method');
            $class->appendChild($method);

            // set basic information
            $method->setAttribute('final', 'false');
            $method->setAttribute('static', 'false');
            $method->setAttribute('visibility', 'public');
            $method->setAttribute('line', $node->getAttribute('line'));
            $method->appendChild(
                new \DOMElement('name', $node->getAttribute('method_name'))
            );

            // fill docblock
            $docblock = new \DOMElement('docblock');
            $method->appendChild($docblock);
            $docblock->appendChild(
                new \DOMElement('description', $node->getAttribute('description'))
            );
            $docblock->appendChild(new \DOMElement('long-description'));

            // for each argument; create an @param tag and an argument element
            /** @var \DOMElement $argument */
            foreach ($node->getElementsByTagName('argument') as $argument) {
                $param_tag = new \DOMElement('tag');
                $docblock->appendChild($param_tag);
                $param_tag->setAttribute('name', 'param');
                $param_tag->setAttribute(
                    'type',
                    $argument->getElementsByTagName('type')->item(0)->nodeValue
                );
                $param_tag->setAttribute(
                    'variable',
                    $argument->getElementsByTagName('name')->item(0)->nodeValue
                );
                $param_tag->setAttribute('line', $node->getAttribute('line'));

                $types = explode(
                    '|',
                    $argument->getElementsByTagName('type')->item(0)->nodeValue
                );

                foreach ($types as $type) {
                    $type_element = new \DOMElement('type', $type);
                    $param_tag->appendChild($type_element);
                }

                $argument_element = $argument->cloneNode(true);
                $method->appendChild($argument_element);
            }

            // add a tag 'magic'
            $magic_tag = new \DOMElement('tag');
            $docblock->appendChild($magic_tag);
            $magic_tag->setAttribute('name', 'magic');
            $magic_tag->setAttribute('line', $node->getAttribute('line'));

            // add a @return tag
            $return_tag = new \DOMElement('tag');
            $docblock->appendChild($return_tag);
            $return_tag->setAttribute('name', 'return');
            $return_tag->setAttribute('line', $node->getAttribute('line'));
            $return_tag->setAttribute('type', $node->getAttribute('type'));

            // add type sub elements to the param
            foreach (explode('|', $node->getAttribute('type')) as $type) {
                $type_element = new \DOMElement('type', $type);
                $return_tag->appendChild($type_element);
            }

            // remove the tag, it is unneeded
            $node->parentNode->removeChild($node);
            $docblock->appendChild($node);
        }

        return $xml;
    }
494451
public static function parseResponseConditionXml(SimpleXMLElement $xml){
        $returnValue = self::parseElementXml($xml);
        foreach($xml->responseIf as $responseIfXml){
            $returnValue['responseIf'] = self::parseResponseIfXml($responseIfXml);
            break;
        }
        foreach($xml->responseElseIf as $responseIfXml){
            if(!isset($returnValue['responseElseIfs'])){
                $returnValue['responseElseIfs'] = array();
            }
            $returnValue['responseElseIfs'][] = self::parseResponseIfXml($responseIfXml);
        }
        foreach($xml->responseElse as $responseIfXml){
            $returnValue['responseElse'] = self::parseResponseElseXml($responseIfXml);
            break;
        }
        return $returnValue;
    }
554559
protected function process($xml)
    {
        if ($this->basedir) {
            $cwd = getcwd();
            chdir($this->basedir);
        }

        // Create and setup document.
        $xmlDom = new DomDocument();
        $xmlDom->resolveExternals = $this->resolveExternals;

        $xmlDom->loadXML($xml);

        $xmlDom->xinclude();

        if ($this->basedir) {
            chdir($cwd);
        }

        return $xmlDom->saveXML();
    }
1102449
public function processSchema( $xsd, $includeElements = false )
	{
		libxml_use_internal_errors();

		$xml = @simplexml_load_file( $xsd );
		if ( ! $xml )
		{
			return false;
		}

		$activeSchemaPrefix = null;

		$prefix = null;
		$targetNamespace = (string) $xml->attributes()->targetNamespace;
		foreach ( $xml->getDocNamespaces() as $namespacePrefix => $namespace )
		{
			if ( ! empty( $namespacePrefix ) && $namespace == SCHEMA_NAMESPACE )
			{
				$activeSchemaPrefix = $namespacePrefix;
			}

			$xml->registerXPathNamespace( $namespacePrefix, $namespace );
			if ( $namespace != $targetNamespace ) continue;
			$prefix = $namespacePrefix;
		}
		$xml->registerXPathNamespace( SCHEMA_PREFIX, SCHEMA_NAMESPACE );

		if ( ! $prefix )
		{
			// If there is no prefix generate a random one
			$prefix = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyz" ), 0, 8 );
		}

		$xpath = new \DOMXPath( dom_import_simplexml( $xml )->ownerDocument );
		$xpath->registerNamespace( SCHEMA_PREFIX, SCHEMA_NAMESPACE );
		$imports = $xpath->query( "/xs:schema/xs:import" );

		foreach ( $imports as $import )
		{
			$nextNamespace = (string) $import->getAttribute( 'namespace' );

			$schemaLocation = (string) $import->getAttribute( 'schemaLocation' );
			$nextXSD = SchemaTypes::resolve_path( $xsd, $schemaLocation );

			$this->processSchema( $nextXSD, $includeElements );
		}

		if ( in_array( $targetNamespace, $this->processedSchemas ) ) return true;

		$this->processedSchemas[ $prefix ] = $targetNamespace;
		$this->activeSchemaPrefix = $activeSchemaPrefix;

		foreach ( $xml->children( SCHEMA_NAMESPACE ) as $nodeKey => $node )
		{
			$this->processNode( $node, $nodeKey, $prefix, $includeElements );
		}

		return true;
	}
786038
final protected function askList($question, $items)
    {
        $indent = ($this->indent > 0) ? $this->indent : 0;
        $question = sprintf('%s%s: ', str_repeat(' ', 4 * $indent), $question);

        $question = new ChoiceQuestion($question, $items);
        return $this->getHelper('question')->ask($this->input, $this->output, $question);
    }
940079
protected function checkUnsupported($xml)
	{
		if (strpos($xml, '<!') !== false)
		{
			throw new InvalidArgumentException('DTDs, CDATA nodes and comments are not allowed');
		}
		if (strpos($xml, '<?') !== false)
		{
			throw new InvalidArgumentException('Processing instructions are not allowed');
		}
	}
1253507
public function import_from_xml($data, $question, qformat_xml $format, $extra=null) {
        $question_type = $data['@']['type'];
        if ($question_type != $this->name()) {
            return false;
        }

        $extraquestionfields = $this->extra_question_fields();
        if (!is_array($extraquestionfields)) {
            return false;
        }

        // Omit table name.
        array_shift($extraquestionfields);
        $qo = $format->import_headers($data);
        $qo->qtype = $question_type;

        foreach ($extraquestionfields as $field) {
            $qo->$field = $format->getpath($data, array('#', $field, 0, '#'), '');
        }

        // Run through the answers.
        $answers = $data['#']['answer'];
        $a_count = 0;
        $extraanswersfields = $this->extra_answer_fields();
        if (is_array($extraanswersfields)) {
            array_shift($extraanswersfields);
        }
        foreach ($answers as $answer) {
            $ans = $format->import_answer($answer);
            if (!$this->has_html_answers()) {
                $qo->answer[$a_count] = $ans->answer['text'];
            } else {
                $qo->answer[$a_count] = $ans->answer;
            }
            $qo->fraction[$a_count] = $ans->fraction;
            $qo->feedback[$a_count] = $ans->feedback;
            if (is_array($extraanswersfields)) {
                foreach ($extraanswersfields as $field) {
                    $qo->{$field}[$a_count] =
                        $format->getpath($answer, array('#', $field, 0, '#'), '');
                }
            }
            ++$a_count;
        }
        return $qo;
    }
1270081
protected function loadCategories($xml){
        //Categories
        if (!$xml->Self){
            return false;
        }
        $cnum = 0;
        foreach($xml->children() as $x){
            $this->data['Categories'][$cnum] = $this->genHierarchy($x);
            $cnum++;
        }
    }
83240
protected function _processTree($nodes)
    {
        foreach ($nodes as $node) {
            if ($node->hasMethods && $node->type !== 'interface') {
                $this->_processMethods($node->tree);
            } elseif (count($node->tree)) {
                $this->_processTree($node->tree);
            }
        }
    }
1020527
public function process($xml)
    {
        // Sanitize if necessary:
        if ($this->sanitize) {
            $xml = $this->sanitizeXml($xml);
        }

        // Parse the XML (newer versions of LibXML require a special flag for
        // large documents, and responses may be quite large):
        $flags = LIBXML_VERSION >= 20900 ? LIBXML_PARSEHUGE : 0;
        $oldSetting = libxml_use_internal_errors(true);
        $result = simplexml_load_string($xml, null, $flags);
        $errors = $this->collectXmlErrors();
        libxml_use_internal_errors($oldSetting);
        if (!$result) {
            throw new \Exception('Problem loading XML: ' . $errors);
        }

        // If we got this far, we have a valid response:
        return $result;
    }
702009
private function deserializeProposals(MatchQuestion $setQuestion, array $items)
    {
        $proposalsEntities = $setQuestion->getProposals()->toArray();

        foreach ($items as $index => $itemData) {
            $proposal = null;

            // Search for an existing Proposal entity.
            foreach ($proposalsEntities as $entityIndex => $entityProposal) {
                /* @var Proposal $entityProposal */
                if ($entityProposal->getUuid() === $itemData['id']) {
                    $proposal = $entityProposal;

                    unset($proposalsEntities[$entityIndex]);
                    break;
                }
            }

            $proposal = $proposal ?: new Proposal();
            $proposal->setUuid($itemData['id']);
            $proposal->setOrder($index);

            // Deserialize proposal content
            $proposal = $this->contentSerializer->deserialize($itemData, $proposal);
            $setQuestion->addProposal($proposal);
        }

        // Remaining proposals are no longer in the Question
        foreach ($proposalsEntities as $proposalToRemove) {
            $setQuestion->removeProposal($proposalToRemove);
        }
    }
305818
public function parse( $xml )
	{
		$this->tree		= $this->parser->parse( $xml );
		$this->outlines	= array();
		$this->headers->clearOptions();

		foreach( $this->parser->getOptions() as $key => $value )
			$this->headers->setOption( "xml_".$key, $value );
		if( $version = $this->tree->getAttribute( "version" ) )
			$this->headers->setOption( "opml_version", $version );

		foreach( $this->tree->getChildren() as $area )
		{
			$areaName	= $area->getNodeName();
			switch( $areaName )
			{
				case "head":
					$children = $area->getChildren();
					foreach( $children as $nr => $child )
					{
						$childName	= $child->getNodeName();
						$content	= $child->getContent();
						switch( $childName )
						{
							case 'dateCreated':
								$content	= $this->getDate( $content );
								break;
							case 'dateModified':
								$content	= $this->getDate( $content );
								break;
							default:
								break;
						}
						$this->headers->setOption( "opml_".$childName, $content );
					}
					break;
				case "body":
					$this->parseOutlines( $area, $this->outlines );
					break;
				default:
					break;
			}
		}
	}
1070820
public function doProcess( $xml ) {

		$domDocument = new DOMDocument();
		$domDocument->loadXml( $xml );

		$this->findElementsForPubMed( $domDocument );
		$this->findElementsForPubMedCentral( $domDocument );
	}
41424
protected function loadXML($xml)
	{
		$this->checkUnsupported($xml);

		// Activate small nodes allocation and relax LibXML's hardcoded limits if applicable. Limits
		// on tags can be set during configuration
		$flags = (LIBXML_VERSION >= 20700) ? LIBXML_COMPACT | LIBXML_PARSEHUGE : 0;

		$useErrors = libxml_use_internal_errors(true);
		$dom       = new DOMDocument;
		$success   = $dom->loadXML($xml, $flags);
		libxml_use_internal_errors($useErrors);

		if (!$success)
		{
			throw new InvalidArgumentException('Cannot load XML: ' . libxml_get_last_error()->message);
		}

		return $dom;
	}