$xp = new domXPath($dom);
$categories=array();
$queries = array(
// [0] - запрос
// [1] - имя нужного параметра для вывода
// [2] - Какой параметр передавать следующей итерации: "0" - категория "1" - группа
// [3] - Иерархия."-1" - запрос выполняется всегда. "лбая другая цифра" - только после этого элемента в дереве. В случае если запросы идут подряд, можно ставить "-1"
array('/component/interface/properties','category',0,-1),
array('/component/interface/properties[@category=\'{CATEGORY}\']/property','name',-1,0),
array('/component/interface/properties[@category=\'{CATEGORY}\']/group_of_props','name',1,0),
array('/component/interface/properties[@category=\'{CATEGORY}\']/group_of_props[@name=\'{GROUP}\']/property','name',-1,2)
);
$elements = array();
function show_tree($i,$category,$group,$l){
global $xp, $queries, $categories, $elements;
$categories[$i] = array();
$query = str_replace(array('{CATEGORY}','{GROUP}'),array($category,$group),$queries[$i][0]);
$elements[$i] = $xp->query($query);
$k=0;
while ($node = $elements[$i]->item($k++))
if(!in_array($new_elem = $node->getAttribute($queries[$i][1]),$categories[$i])){
$categories[$i][] = $new_elem;
for($n=0;$n<$l;$n++) print('_');
print($new_elem.'<BR>');
for($n=$i;$n<count($queries)-1;$n++)
if(($queries[$n+1][3]==$i)or($queries[$n+1][3]==-1)){
if($queries[$i][2]==1) show_tree($n+1,$category,$new_elem,$l+1);
elseif($queries[$i][2]==0) show_tree($n+1,$new_elem,$group,$l+1);
else show_tree($n+1,$category,$group,$l+1);
}
}
}
show_tree(0,'','',0);