xml-parsingphp-5.6php-7.1ims

PHP7 xml_parse() changes, truncated arrays?


The problem I'm having occurs with the xml_parse() function in the ATutor QTI Parser

I'm hoping someone can point out what I'm missing, or perhaps come up with a work around for PHP 7.1.1.

I've found no documentation, or posts here, that suggest changes to the PHP xml_parse() function from 5.6 to 7.1, though the two versions seem to parse xml differently. The XML being parse appears below.

Specifically, for the question array in the examples, 5.6.30 returns an array of questions, like:

[question] => Array
    (
        [0] => graphic matching
        [1] => LIKERT
        [2] => multi choice question
        [3] => Mutliple question
        [4] => open ended
        [5] => ordering
        [6] => Simple match
        [7] => true
    )

While with php 7.1.1, all else being the same, it returns only the first letters from each of the array elements above, as a string.

[question] => gLmMooSt

The XML file is an IMS QTI 1.2.1 manifest, from a QTI test (i.e. quiz) package.

The element where the truncating occurs is the question title (the question itself), found in the following element, which returns as the first element in the array when using PHP5.6 ([0] => graphic matching), and return as the first letter, "g", in the question string when using PHP7.1.1 ([question] => gLmMooSt)

<material>
        <mattext texttype="text/html">graphic matching</mattext>
</material>

<?xml version="1.0" encoding="utf-8"?>

<questestinterop  
  xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_4/ims_qtiasiv1p2_localised.xsd"
>
	<assessment title="Simple test" ident="d41d8cd98f00b204e9800998ecf8427e">
                
		<section ident="ATUTOR-8" title="Simple test">
		<!-- matching question with partial marks -->
		<item title="Mathcing question" ident="ITEM_2">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Groups</fieldentry>
					</qtimetadatafield>
					<qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>Drag-and-drop</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.pattern_match.v0p1</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_weighting</fieldlabel>
                        <fieldentry>5</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">graphic matching</mattext>
					</material>
							
					<response_lid ident="RESPONSE-98f13708210194c475687be6106a3b84" rcardinality="Multiple">
						<material>
							<mattext texttype="text/html">a</mattext>
						</material>
						<render_choice shuffle="No">
													<response_label ident="Option0">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">A</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Option1">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">B</mattext>
									</material>
								</flow_mat>
							</response_label>
												</render_choice>
					</response_lid>
							
					<response_lid ident="RESPONSE-3c59dc048e8850243be8079a5c74d079" rcardinality="Multiple">
						<material>
							<mattext texttype="text/html">b</mattext>
						</material>
						<render_choice shuffle="No">
													<response_label ident="Option0">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">A</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Option1">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">B</mattext>
									</material>
								</flow_mat>
							</response_label>
												</render_choice>
					</response_lid>
									</flow>
			</presentation>

			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
																				</resprocessing>
				</item>


<!-- likert question (aka multiple choice with no correct answer) -->
		<item title="Multiple choice question" ident="ITEM_1">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Identifier</fieldentry>
					</qtimetadatafield>
					<qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>Multiple-choice</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.mutliple_choice.v0p1</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">LIKERT</mattext>
					</material>
					<response_lid ident="RESPONSE1" rcardinality="Single">
						<render_choice shuffle="No" minnumber="1" maxnumber="1">
							<flow_label>
															<response_label ident="Choice0">	
									<material>
										<mattext texttype="text/html">A LITTLE</mattext>
									</material>
								</response_label>
															<response_label ident="Choice1">	
									<material>
										<mattext texttype="text/html">A lot</mattext>
									</material>
								</response_label>
														</flow_label>
						</render_choice>
					</response_lid>
				</flow>
			</presentation>

			<resprocessing>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE1">Choice0</varequal>
					</conditionvar>
					<setvar varname="que_score" action="Set">0</setvar>
				</respcondition>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE1">Choice1</varequal>
					</conditionvar>
					<setvar varname="que_score" action="Set">0</setvar>
				</respcondition>
							</resprocessing>
		</item>


<!-- single answer multiple choice question -->
		<item title="Multiple choice question" ident="ITEM_5">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Identifier</fieldentry>
					</qtimetadatafield>
					<qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>Multiple-choice</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.mutliple_choice.v0p1</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_weighting</fieldlabel>
                        <fieldentry>5</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">multi choice question</mattext>
					</material>
					<response_lid ident="RESPONSE5" rcardinality="Single">
						<render_choice shuffle="No" minnumber="1" maxnumber="1">
													<response_label ident="Choice0">
								<flow_mat>
									<material>
										<mattext texttype="text/html">this is correct</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Choice1">
								<flow_mat>
									<material>
										<mattext texttype="text/html">this is wrong</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Choice2">
								<flow_mat>
									<material>
										<mattext texttype="text/html">this is wrong</mattext>
									</material>
								</flow_mat>
							</response_label>
												</render_choice>
					</response_lid>
				</flow>
			</presentation>
			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
													<respcondition title="CorrectResponse">
					<conditionvar>						
						<varequal respident="RESPONSE5">Choice0</varequal>
					</conditionvar>
					<setvar varname="que_score" action="Set">5</setvar>
				</respcondition>
																																	
			</resprocessing>
				</item>

<!-- multi answer multiple choice question with partial marks -->
		<item title="Multiple answer question" ident="ITEM_4">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Identifier</fieldentry>
					</qtimetadatafield>
	                <qtimetadatafield>
                        <fieldlabel>qmd_questiontype</fieldlabel>
                        <fieldentry>Multiple-response</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.mutliple_response.v0p1</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_weighting</fieldlabel>
                        <fieldentry>5</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">Mutliple question</mattext>
					</material>
					<response_lid ident="RESPONSE4" rcardinality="Multiple">
						<render_choice shuffle="No">
													<response_label ident="Choice0">
								<flow_mat>
									<material>
										<mattext texttype="text/html">coorect</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice1">
								<flow_mat>
									<material>
										<mattext texttype="text/html">coorect</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice2">
								<flow_mat>
									<material>
										<mattext texttype="text/html">icorrect</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice3">
								<flow_mat>
									<material>
										<mattext texttype="text/html">icorrect</mattext>
									</material>
								</flow_mat>
							</response_label>
													</render_choice>
					</response_lid>
				</flow>
			</presentation>
			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
											<respcondition title="CorrectResponse">
					<conditionvar>						
						<varequal respident="RESPONSE4">Choice0</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">5</setvar>
				</respcondition>
															<respcondition title="CorrectResponse">
					<conditionvar>						
						<varequal respident="RESPONSE4">Choice1</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">5</setvar>
				</respcondition>
																								</resprocessing>
				</item>


<!-- open ended (free text) question -->
		<item title="Open ended question" ident="ITEM_6">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>String</fieldentry>
					</qtimetadatafield>
					<qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>FIB-string</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.fib.v0p1</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_weighting</fieldlabel>
                        <fieldentry>5</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">open ended</mattext>
					</material>
					<response_str ident="RESPONSE6" rcardinality="Single">
												<render_fib rows="1" columns="5">
							<response_label ident="Choice" />
						</render_fib>
					</response_str>
				</flow>
			</presentation>
				</item>


<!-- ordering question -->
		<item title="Ordering question" ident="ITEM_7">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Identifier</fieldentry>
					</qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">ordering</mattext>
					</material>
					<response_lid ident="RESPONSE7" rcardinality="Ordered">
						<render_choice shuffle="Yes" minnumber="4" maxnumber="4">
														<response_label ident="Choice0">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">item1</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice1">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">itms2</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice2">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">item 3</mattext>
									</material>
								</flow_mat>
							</response_label>
														<response_label ident="Choice3">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">items 4</mattext>
									</material>
								</flow_mat>
							</response_label>
													</render_choice>
					</response_lid>
				</flow>
			</presentation>
			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE7">Choice0</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">1.25</setvar>
				</respcondition>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE7">Choice1</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">1.25</setvar>
				</respcondition>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE7">Choice2</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">1.25</setvar>
				</respcondition>
								<respcondition title="CorrectResponse">
					<conditionvar>					
						<varequal respident="RESPONSE7">Choice3</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">1.25</setvar>
				</respcondition>
							</resprocessing>
				</item>


<!-- matching question with partial marks -->
		<item title="Mathcing question" ident="ITEM_3">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Groups</fieldentry>
					</qtimetadatafield>
					<qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>Drag-and-drop</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_profile</fieldlabel>
                        <fieldentry>cc.pattern_match.v0p1</fieldentry>
                    </qtimetadatafield>
                    <qtimetadatafield>
                        <fieldlabel>cc_weighting</fieldlabel>
                        <fieldentry>5</fieldentry>
                    </qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">Simple match</mattext>
					</material>
							
					<response_lid ident="RESPONSE-34173cb38f07f89ddbebc2ac9128303f" rcardinality="Multiple">
						<material>
							<mattext texttype="text/html">A</mattext>
						</material>
						<render_choice shuffle="No">
													<response_label ident="Option0">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">A</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Option1">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">B</mattext>
									</material>
								</flow_mat>
							</response_label>
												</render_choice>
					</response_lid>
							
					<response_lid ident="RESPONSE-c16a5320fa475530d9583c34fd356ef5" rcardinality="Multiple">
						<material>
							<mattext texttype="text/html">B</mattext>
						</material>
						<render_choice shuffle="No">
													<response_label ident="Option0">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">A</mattext>
									</material>
								</flow_mat>
							</response_label>
													<response_label ident="Option1">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">B</mattext>
									</material>
								</flow_mat>
							</response_label>
												</render_choice>
					</response_lid>
									</flow>
			</presentation>

			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
											<respcondition title="CorrectResponse">
					<conditionvar>						
						<varequal respident="RESPONSE-34173cb38f07f89ddbebc2ac9128303f">Option0</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">5</setvar>
				</respcondition>
															<respcondition title="CorrectResponse">
					<conditionvar>						
						<varequal respident="RESPONSE-c16a5320fa475530d9583c34fd356ef5">Option1</varequal>
					</conditionvar>
					<setvar varname="Respondus_Correct">5</setvar>
				</respcondition>
										</resprocessing>
					<itemfeedback ident="FEEDBACK">
				<solution>
					<solutionmaterial>
						<flow_mat>
							<material>
								<mattext texttype="text/html">Optional Feedback</mattext>
							</material>
						</flow_mat>
					</solutionmaterial>
				</solution>
			</itemfeedback>
				</item>


<!-- true or false question (aka multiple choice with two choices) -->
		<item title="True or False question" ident="ITEM_8">
			<itemmetadata>
				<qtimetadata>
					<qtimetadatafield>
						<fieldlabel>qmd_itemtype</fieldlabel>
						<fieldentry>Logical Identifier</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
						<fieldlabel>qmd_questiontype</fieldlabel>
						<fieldentry>True/false</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
						<fieldlabel>cc_profile</fieldlabel>
						<fieldentry>cc.true_false.v0p1</fieldentry>
					</qtimetadatafield>
                    <qtimetadatafield>
						<fieldlabel>cc_weighting</fieldlabel>
						<fieldentry>5</fieldentry>
					</qtimetadatafield>
				</qtimetadata>
			</itemmetadata>
			<presentation>
				<flow>
					<material>
						<mattext texttype="text/html">true</mattext>
					</material>
					<response_lid ident="RESPONSE8" rcardinality="Single">
						<render_choice shuffle="No">
							<response_label ident="ChoiceT">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">True</mattext>
									</material>
								</flow_mat>
							</response_label>
							<response_label ident="ChoiceF">	
								<flow_mat>
									<material>
										<mattext texttype="text/html">False</mattext>
									</material>
								</flow_mat>
							</response_label>
						</render_choice>
					</response_lid>
				</flow>
			</presentation>
			<resprocessing>
				<outcomes>
					<decvar varname="SCORE" />
				</outcomes>
				<respcondition title="CorrectResponse">
					<conditionvar>
						<varequal respident="RESPONSE8">
							ChoiceT						</varequal>
					</conditionvar>
					<setvar varname="que_score" action="Set">5</setvar>
				</respcondition>
			</resprocessing>
				</item>		</section>
	</assessment>
</questestinterop>


Solution

  • This issue is caused by that, the variable $question for holding an array is initiated as an empty string.

    PHP7 has a much strict variable type validation. Before PHP7, when a variable is treated as a different type in the code than the type it initiates as, PHP silently convert it to the new type. With PHP7, the variable is treated as the initialized type throughout the code, in this case results in array values assigned to $question are truncated to compose a string by only taking the first character from each array value.