I have an array like \'var1\'=>1.05, \'var2\'=>0.76,...
and a forest of binary trees stored in a 100+ MB XML file.
You're on the right track with XMLReader. Rather conveniently it includes the method expand() which will return a copy of the current node as a DOMNode. This will let you handle each individual Tree in memory with the DOM API.
As for handling nodes - evaluate and descend recursively.
$data = [
'var1' => 1.05,
'var2' => 0.76
];
$dom = new DOMDocument();
$xpath = new DOMXPath($dom);
$reader = new XMLReader();
$reader->open('forest.xml');
// Read until reaching the first Tree.
while ($reader->read() && $reader->localName !== 'Tree');
while ($reader->localName === 'Tree') {
$tree = $dom->importNode($reader->expand(), true);
echo evaluateTree($data, $tree, $xpath), "\n";
// Move on to the next.
$reader->next('Tree');
}
$reader->close();
function evaluateTree(array $data, DOMElement $tree, DOMXPath $xpath)
{
foreach ($xpath->query('./Node', $tree) as $node) {
$field = $xpath->evaluate('string(./SimplePredicate/@field)', $node);
$operator = $xpath->evaluate('string(./SimplePredicate/@operator)', $node);
$value = $xpath->evaluate('string(./SimplePredicate/@value)', $node);
if (evaluatePredicate($data[$field], $operator, $value)) {
// Descend recursively.
return evaluateTree($data, $node, $xpath);
}
}
// Reached the end of the line.
return $tree->getAttribute('id');
}
function evaluatePredicate($left, $operator, $right)
{
switch ($operator) {
case "lessOrEqual":
return $left <= $right;
case "greaterThan":
return $left > $right;
default:
return false;
}
}
4