Skip to content

Commit

Permalink
fix: parse special symbols on XML
Browse files Browse the repository at this point in the history
  • Loading branch information
kilatib committed Nov 6, 2024
1 parent 28b6382 commit d93c7e0
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/qtism/data/storage/xml/Utils.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -353,11 +355,30 @@ public static function valueAsString($value, $encode = true): string
return $value === true ? 'true' : 'false';
}
if ($encode) {
return htmlspecialchars((string)$value, ENT_XML1, 'UTF-8');
return self::escapeNonCharacterRange((string)$value);
}
return (string)$value;
}

public static function escapeNonCharacterRange(string $string): string
{
// Define the XML escape sequences
$symbolMap = [
'"' => '&quot;',
"'" => '&apos;',
'&' => '&amp;',
'<' => '&lt;',
'>' => '&gt;',
"\t" => '&#x9;',
"\r" => '&#xD;',
"\x08" => '&#xFFFD;',
];

$string = strtr($string, $symbolMap);

return htmlspecialchars($string, ENT_QUOTES | ENT_XML1, 'UTF-8');
}

/**
* Get the child elements of a given element by tag name. This method does
* not behave like DOMElement::getElementsByTagName. It only returns the direct
Expand Down
46 changes: 46 additions & 0 deletions test/qtismtest/data/storage/xml/XmlUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,52 @@ public function testFindCustomNamespaces(): void
);
}

public function testValueAsStringReplaceSpecialSymbols(): void
{
$xml = ('<value>160°</value>');
$this->assertEquals('&amp;lt;value&amp;gt;160°&amp;#xFFFD;&amp;lt;/value&amp;gt;', Utils::valueAsString($xml));
}

public function testProcessSpecialCharsetWithoutError(): void
{
$xml = ('<?xml version="1.0" encoding="UTF-8"?>
<assessmentResult
xmlns="http://www.imsglobal.org/xsd/imsqti_result_v2p1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<context/>
<testResult identifier="44127db28512-suomynona#903756e974e7#e94025be336b1f89159af64b1f6eda5d470ac8d61#local-dev-acc.nextgen-stack-local" datestamp="2024-10-30T12:56:32+00:00"/>
<itemResult identifier="item-1" datestamp="2024-10-30T12:56:32+00:00" sessionStatus="final">
<responseVariable identifier="numAttempts" cardinality="single" baseType="integer">
<candidateResponse>
<value>1</value>
</candidateResponse>
</responseVariable>
<responseVariable identifier="duration" cardinality="single" baseType="duration">
<candidateResponse>
<value>PT22S</value>
</candidateResponse>
</responseVariable>
<outcomeVariable identifier="completionStatus" cardinality="single" baseType="identifier">
<value>completed</value>
</outcomeVariable>
<outcomeVariable identifier="SCORE" cardinality="single" baseType="float">
<value>0</value>
</outcomeVariable>
<outcomeVariable identifier="MAXSCORE" cardinality="single" baseType="float">
<value>1</value>
</outcomeVariable>
<responseVariable identifier="RESPONSE" cardinality="single" baseType="string">
<candidateResponse>
<value>%s</value>
</candidateResponse>
</responseVariable>
</itemResult>
</assessmentResult>
');
$this->assertNotNull(Utils::findExternalNamespaces(sprintf($xml, Utils::valueAsString('160°'))));
}


public function testremoveAllButFirstOccurrence(): void
{
$subject = 'abc 12 abc 345abc678abc';
Expand Down

0 comments on commit d93c7e0

Please sign in to comment.