PHP:按多个元素对XML节点列表进行排序

时间:2015-05-18 14:40:57

标签: php xml sorting xpath

初学者程序员。

我在php中,使用dom文档节点列表,该节点列表包含从xml文件上的XPath查询中检索到的选定节点。节点列表的内容摘录:

<properties>
    <property>
        <price>270</price>
        <address>3/2 Farran Street, Castlemaine, VIC, Australia</address>
        <infants>3</infants>
    </property>
    <property>
        <price>250</price>
        <address>2/37 William Street, Castlemaine, VIC, Australia</address>
        <infants>2</infants>
    </property>
    <property>
        <price>250</price>
        <address>2/37 William Street, Castlemaine, VIC, Australia</address>
        <infants>3</infants>
    </property>
    ...

我希望按price升序对节点列表进行排序,如果匹配价格,则按infants降序排序。例如,在上面的代码段中,结果将是:

<property>
    <price>250</price>
    <address>2/37 William Street, Castlemaine, VIC, Australia</address>
    <infants>3</infants>
</property>
<property>
    <price>250</price>
    <address>2/37 William Street, Castlemaine, VIC, Australia</address>
    <infants>2</infants>
</property>
<property>
    <price>270</price>
    <address>3/2 Farran Street, Castlemaine, VIC, Australia</address>
    <infants>3</infants>
</property>

我已经看到一些与多维数组有关的排序问题,但我似乎无法将这些问题转换为节点列表。我可以按price排序(见下文),但我无法确定如何按infants排序。

$properties = iterator_to_array($matches); // where matches = a return from an XPath query
usort($properties, 'sortByPrice');

function sortByPrice ($a, $b) {
    $aPrice = $a->getElementsByTagName("price");
    $aPrice = $aPrice->item(0)->nodeValue;
    $bPrice = $b->getElementsByTagName("price");
    $bPrice = $bPrice->item(0)->nodeValue;
    return (int) $aPrice - (int) $bPrice;
}

3 个答案:

答案 0 :(得分:0)

如果您的代码适用于价格,为什么不直接扩展它:

$properties = iterator_to_array($matches); // where matches = a return from an XPath query
usort($properties, 'sortByPrice');

function sortByPrice ($a, $b) {
    $aPrice = $a->getElementsByTagName("price");
    $aPrice = $aPrice->item(0)->nodeValue;
    $bPrice = $b->getElementsByTagName("price");
    $bPrice = $bPrice->item(0)->nodeValue;
    $r = (int) $aPrice - (int) $bPrice;
    if (!$r) {
       $ainfants = $a->getElementsByTagName("infants");
       $ainfants = $ainfants->item(0)->nodeValue;
       $binfants = $b->getElementsByTagName("infants");
       $binfants = $bPrice->item(0)->nodeValue;
       $r = (int) $ainfants - (int) $binfants;
    }
    return $r;
}

答案 1 :(得分:0)

您可以根据具有DOMXPath::evaluate()的上下文节点来获取标量值。 number()会将位置路径结果中的第一个节点强制转换为浮点数。如果没有找到节点,则结果为零。

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

$properties = iterator_to_array($xpath->evaluate('//properties/property'));
usort(
  $properties,
  function(DOMElement $a, DOMElement $b) use ($xpath) {
    $aPrice = (int)$xpath->evaluate('number(price)', $a);
    $bPrice = (int)$xpath->evaluate('number(price)', $b);
    if ($aPrice == $bPrice) {
      $aInfants = (int)$xpath->evaluate('number(infants)', $a);
      $bInfants = (int)$xpath->evaluate('number(infants)', $b);
      return $bInfants - $aInfants;
    }
    return $aPrice - $bPrice;
  }
);

答案 2 :(得分:-1)

试试这个功能。它充当uasort PHP函数的推广:

function sortByKeyValue($the_array, $key)
{
   $cmp_val="((\$a['$key']>\$b['$key'])?1:
   ((\$a['$key']==\$b['$key'])?0:-1))";
   $cmp=create_function('$a, $b', "return $cmp_val;");
   uasort($the_array, $cmp);

   return $the_array;
}

在您的情况下,您可以这样使用它:

$properties = iterator_to_array($matches);
sortByKeyValue($properties, 'price');
sortByKeyValue($properties, 'infants');

我希望它有所帮助。