【发布时间】:2011-11-03 07:04:03
【问题描述】:
<root>
<a auto='1'>
<b>
<c auto="1">
<d auto="1"></d>
</c>
</b>
<e auto="1">
<f>
<g auto="1"></g>
</f>
</e>
</a>
</root>
找到所有的元素
- 是上下文元素的后代
- 有
auto属性 - 最高级别(在 self 和上下文元素之间没有具有
auto属性的祖先)
因此,如果上下文节点是a,则应返回c 和e。
我已经在我的 php 类中实现了它:
$tempId='XDFAY69LA';
$this->setAttribute('tempId',$tempId);
$path=".//\*[@auto and not(ancestor::\*[@auto and ancestor::\*[@tempId='$tempId']])]";
$ar=$this->getElementsByXPath($path);
$this->removeAttribute('tempId');
但是我发现查询很慢,也许..,因为查询太复杂了?,有没有办法做得更好?
我写了一个测试,请看一下:
<?php
$xml='
<root>
<a auto="1" tempId="current">
<b>
<c auto="1">
<d auto="1"></d>
</c>
</b>
<e auto="1">
<f>
<g auto="1"></g>
</f>
</e>
</a>
</root> ';
$doc=new DomDocument();
$tempId='XDFAY69LA';
$doc->loadXml($xml);
$domxpath=new DOMXPath($doc);
$a=$domxpath->query('a')->item(0);
$path=".//*[@auto and not(ancestor::*[@auto and ancestor::*[@tempId='$tempId']])]";
$start=microtime(true);
for($n=0;$n<1000;$n++){ //run 1000 times
$a->setAttribute('tempId',$tempId);
$ar=$domxpath->query($path,$a);
$a->removeAttribute('tempId');
for($i=0;$i<$ar->length;$i++){
$node=$ar->item($i);
//echo $node->tagName . "\n";
}
}
$cost=round(1000 * (microtime(true)-$start));
echo "time cost: $cost";
?>
【问题讨论】:
-
好问题,+1。请参阅我的答案以获得更短的 XPath 表达式以及使用 XSLT 和键的更快解决方案的演示。如果您被禁止使用 XSLT,您可以使用哈希表实现类似的解决方案。