我有一个像这样的数组'var1'=>1.05, 'var2'=>0.76,...
以及存储在 100+ MB XML 文件中的二叉树森林。
<Tree id="1">
<Node id="2">
<SimplePredicate field="var1" operator="lessOrEqual" value="1.41"/>
<Node id="4">
<SimplePredicate field="var2" operator="lessOrEqual" value="1.43"/>
.......
</Node>
</Node>
<Node id="3">
<SimplePredicate field="var1" operator="greaterThan" value="1.41"/>
.......
</Node>
</Tree>
我想在 PHP 中做的是为每棵树存储叶子的属性,我将根据每个节点给出的条件最终得到叶子的属性。因此,在此示例中,路径将为 (2)->(4)->...
由于文件大小,很明显 XMLReader 是读取每棵树的合适工具。由于树非常小,因此可以在处理每个树时将它们存储到内存中。
处理树木最直接的方法是什么?
使用 XMLReader,您的方向是正确的。它相当方便地包括该方法expand() http://php.net/manual/en/xmlreader.expand.php它将返回当前节点的副本作为DOMNode http://php.net/manual/en/class.domnode.php。这将使您可以使用以下方法处理内存中的每个单独的树DOM API http://php.net/manual/en/book.dom.php.
至于处理节点 - 递归地评估和下降。
Example:
$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;
}
}
Output:
4
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)