24
Sep/090
Sep/090
XML selectNodes() ordered
Here is a helper function to select nodes from an XML document order by certain child node value of these nodes.
If selectNodes() is a pendant of MySQL SELECT command, this helper function would be a pendant of SELECT… ORDER BY…
As far I know there is no standart XML or XPath function to perform it.
Written in PHP for DOM Document model.
By default, the function sorts descending. To sort ascending, remove the comment on the end of function body.
In this example, nodes will be sorted by node value of the field range:
$str='<root> <sub><snode><p><range>0</range><text>node5</text></p></snode></sub> <sub><snode><p><range>2</range><text>node1</text></p></snode></sub> <sub><snode><p><range>1</range><text>node2</text></p></snode></sub> <sub><snode><p><range>5</range><text>node3</text></p></snode></sub> <sub><snode><p><range>4</range><text>node4</text></p></snode></sub> <sub><snode><p><range>38</range><text>this</text></p></snode></sub> </root>'; $dom=new DomDocument(); $dom->loadXML($str); $ordered_array=getSortedNodes($dom->documentElement,'snode','range'); foreach($ordered_array as $n) { echo $n->nodeName.' '.$n->getElementsByTagName('range')->item(0)->nodeValue.'<br>'; } /** * @returns array */ function getSortedNodes($parentNode,$sortedNodeName, $rangeNodeName='range') { $snodes=$parentNode->getElementsByTagName($sortedNodeName); $snodes_array=array(); foreach($snodes as $snode) $snodes_array[]=$snode; $new=array(); $max=0; $i=0; $rangeNodes=$parentNode->getElementsByTagName($rangeNodeName); $rangeNodesLength=$rangeNodes->length; //exclude elements with range value=0 because of unknown error foreach($rangeNodes as $rN) { if((float)$rN->nodeValue==0) $rangeNodesLength--; } while($i<$rangeNodesLength) { foreach($snodes_array as $key=>$snode) { $range=$snode->getElementsByTagName($rangeNodeName)->item(0); if($range) { if((float)$range->nodeValue > $max) { $max=$range->nodeValue; $tmp=$range->parentNode; //if the range node is not directly in $parentNode while($tmp->nodeName!=$sortedNodeName) $tmp=$tmp->parentNode; $max_snode=$tmp; $max_key=$key; } } } $new[]=$max_snode; $max=0; unset($snodes_array[$max_key]); $i++; } //$new=array_reverse($new,true); - to sort ascending return $new; }
