public function parse($xmlString)
{
if ($this->validateResponse) {
XmlChecker::validXml($xmlString);
}
$useErrors = libxml_use_internal_errors(true);
$xml = new XMLReader();
$xml->xml($xmlString, 'UTF-8', LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS | LIBXML_PARSEHUGE);
$xml->setParserProperty(XMLReader::VALIDATE, false);
$xml->setParserProperty(XMLReader::LOADDTD, false);
// This following assignments are auto-generated using fXmlRpc\CodeGenerator\XmlReaderParserBitmaskGenerator
// Don’t edit manually
static $flagmethodResponse = 0b1;
static $flagparams = 0b10;
static $flagfault = 0b100;
static $flagparam = 0b1000;
static $flagvalue = 0b10000;
static $flagarray = 0b100000;
static $flagmember = 0b1000000;
static $flagname = 0b10000000;
${'flag#text'} = 0b100000000;
static $flagstring = 0b1000000000;
static $flagstruct = 0b10000000000;
static $flagint = 0b100000000000;
static $flagbiginteger = 0b1000000000000;
static $flagi8 = 0b10000000000000;
static $flagi4 = 0b100000000000000;
static $flagi2 = 0b1000000000000000;
static $flagi1 = 0b10000000000000000;
static $flagboolean = 0b100000000000000000;
static $flagdouble = 0b1000000000000000000;
static $flagfloat = 0b10000000000000000000;
static $flagbigdecimal = 0b100000000000000000000;
${'flagdateTime.iso8601'} = 0b1000000000000000000000;
static $flagdateTime = 0b10000000000000000000000;
static $flagbase64 = 0b100000000000000000000000;
static $flagnil = 0b1000000000000000000000000;
static $flagdom = 0b10000000000000000000000000;
static $flagdata = 0b100000000000000000000000000;
// End of auto-generated code
$aggregates = [];
$depth = 0;
$nextExpectedElements = 0b1;
$i = 0;
$isFault = false;
while ($xml->read()) {
$i++;
$nodeType = $xml->nodeType;
if ($nodeType === XMLReader::COMMENT || $nodeType === XMLReader::DOC_TYPE || $nodeType === XMLReader::SIGNIFICANT_WHITESPACE && ($nextExpectedElements & 0b100000000) !== 0b100000000) {
continue;
}
if ($nodeType === XMLReader::ENTITY_REF) {
libxml_use_internal_errors($useErrors);
return '';
}
$tagName = $xml->localName;
if ($nextExpectedElements !== null && ($flag = isset(${'flag' . $tagName}) ? ${'flag' . $tagName} : -1) && ($nextExpectedElements & $flag) !== $flag) {
libxml_use_internal_errors($useErrors);
throw ParserException::unexpectedTag($tagName, $nextExpectedElements, get_defined_vars(), $xml->depth, $xml->readOuterXml());
}
processing:
switch ($nodeType) {
case XMLReader::ELEMENT:
switch ($tagName) {
case 'methodResponse':
// Next: params, fault
$nextExpectedElements = 0b110;
break;
case 'params':
// Next: param
$nextExpectedElements = 0b1000;
$aggregates[$depth] = [];
$isFault = false;
break;
case 'fault':
$isFault = true;
// Break intentionally omitted
// Break intentionally omitted
case 'param':
// Next: value
$nextExpectedElements = 0b10000;
break;
case 'array':
$aggregates[++$depth] = [];
// Break intentionally omitted
// Break intentionally omitted
case 'data':
// Next: array, data, value
$nextExpectedElements = 0b100000000000000000000110000;
break;
case 'struct':
// Next: struct, member, value
$nextExpectedElements = 0b10001010000;
$aggregates[++$depth] = [];
break;
case 'member':
// Next: name, value
$nextExpectedElements = 0b10010000;
$aggregates[++$depth] = [];
break;
case 'name':
// Next: #text
$nextExpectedElements = 0b100000000;
$type = 'name';
break;
case 'value':
$nextExpectedElements = 0b11111111111111111100110000;
$type = 'value';
$aggregates[$depth + 1] = '';
break;
case 'base64':
case 'string':
case 'biginteger':
case 'i8':
case 'dateTime.iso8601':
case 'dateTime':
// Next: value, $tagName, #text
$nextExpectedElements = 0b100010000 | ${'flag' . $tagName};
$type = $tagName;
$aggregates[$depth + 1] = '';
break;
case 'nil':
// Next: value, $tagName
$nextExpectedElements = 0b1000000000000000000010000 | ${'flag' . $tagName};
$type = $tagName;
$aggregates[$depth + 1] = null;
break;
case 'int':
case 'i4':
case 'i2':
case 'i1':
// Next: value, #text, $tagName
$nextExpectedElements = 0b100010000 | ${'flag' . $tagName};
$type = $tagName;
$aggregates[$depth + 1] = 0;
break;
case 'boolean':
// Next: value, #text, $tagName
$nextExpectedElements = 0b100010000 | ${'flag' . $tagName};
$type = 'boolean';
$aggregates[$depth + 1] = false;
break;
case 'double':
case 'float':
case 'bigdecimal':
// Next: value, #text, $tagName
$nextExpectedElements = 0b100010000 | ${'flag' . $tagName};
$type = $tagName;
$aggregates[$depth + 1] = 0.0;
break;
case 'dom':
$type = 'dom';
// Disable type checking
$nextExpectedElements = null;
$aggregates[$depth + 1] = $xml->readInnerXml();
break;
}
break;
case XMLReader::END_ELEMENT:
switch ($tagName) {
case 'params':
case 'fault':
break 3;
case 'param':
// Next: params, param
$nextExpectedElements = 0b1010;
break;
case 'value':
$nextExpectedElements = 0b100100000011100100011011100;
$aggregates[$depth][] = $aggregates[$depth + 1];
break;
case 'array':
case 'struct':
--$depth;
// Break intentionally omitted
// Break intentionally omitted
case 'string':
case 'int':
case 'biginteger':
case 'i8':
case 'i4':
case 'i2':
case 'i1':
case 'boolean':
case 'double':
case 'float':
case 'bigdecimal':
case 'dateTime.iso8601':
case 'dateTime':
case 'base64':
case 'nil':
// Next: value
$nextExpectedElements = 0b10000;
break;
case 'data':
// Next: array
$nextExpectedElements = 0b100000;
break;
case 'name':
// Next: value, member
$nextExpectedElements = 0b1010000;
$aggregates[$depth]['name'] = $aggregates[$depth + 1];
break;
case 'member':
// Next: struct, member
$nextExpectedElements = 0b10001000000;
$aggregates[$depth - 1][$aggregates[$depth]['name']] = $aggregates[$depth][0];
unset($aggregates[$depth], $aggregates[$depth + 1]);
--$depth;
break;
}
break;
case XMLReader::TEXT:
case XMLReader::SIGNIFICANT_WHITESPACE:
switch ($type) {
case 'int':
case 'i4':
case 'i2':
case 'i1':
$value = (int) $xml->value;
break;
case 'boolean':
$value = $xml->value === '1';
break;
case 'double':
case 'float':
case 'bigdecimal':
$value = (double) $xml->value;
break;
case 'dateTime.iso8601':
$value = DateTime::createFromFormat('Ymd\\TH:i:s', $xml->value, isset($timezone) ? $timezone : ($timezone = new DateTimeZone('UTC')));
break;
case 'dateTime':
$value = DateTime::createFromFormat('Y-m-d\\TH:i:s.uP', $xml->value, isset($timezone) ? $timezone : ($timezone = new DateTimeZone('UTC')));
break;
case 'base64':
$value = Base64::deserialize($xml->value);
break;
case 'dom':
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadXML($aggregates[$depth + 1]);
$value = $doc;
break;
default:
$value =& $xml->value;
break;
}
$aggregates[$depth + 1] = $value;
if ($nextExpectedElements === null) {
break;
}
// Next: any
$nextExpectedElements = 0b111111111111111111111111111;
break;
}
if ($xml->isEmptyElement && $nodeType !== XMLReader::END_ELEMENT) {
$nodeType = XMLReader::END_ELEMENT;
goto processing;
}
}
libxml_use_internal_errors($useErrors);
$result = $aggregates ? array_pop($aggregates[0]) : null;
if ($isFault) {
throw FaultException::fault($result);
}
return $result;
}