2009-08-31 38 views
5

Tengo un archivo XML que estoy intentando recorrer en orden, según el atributo "orden".Ordenar XML a través del valor de atributo PHP

Aquí se muestra un ejemplo:

<page> 
<talentTrees> 
<tree name="Football" order="2"> 
<tree name="Baseball" order="0"> 
<tree name="Frisbee" order="1"> 
</talentTrees> 
</page> 

Mi objetivo es recorrer cada "árbol" usando foreach, pero quiero leerlos con el fin del atributo orden: béisbol, disco volador, Fútbol. (0,1,2).

Lo siento por un inglés pobre, no es mi primer idioma.

Respuesta

6

Esto debe darle lo que quiere:

$string = <<<EOS 
<page> 
<talentTrees> 
<tree name="Football" order="2" /> 
<tree name="Baseball" order="0" /> 
<tree name="Frisbee" order="1" /> 
</talentTrees> 
</page> 
EOS; 

$xml = simplexml_load_string($string); 

$trees = $xml->xpath('/page/talentTrees/tree'); 
function sort_trees($t1, $t2) { 
    return strcmp($t1['order'], $t2['order']); 
} 

usort($trees, 'sort_trees'); 
var_dump($trees); 

$trees ahora están clasificados por el atributo de orden.

+1

Esto falla cuando los números son más grandes que 9. Será ordenar así: 1, 100, 2, 245, 300, 4. En lugar de 1, 2, 4, 100, 245, 300. Use la sugerencia de Josh Davis a continuación. Funciona bien. – matthoiland

0

This page da algunos grandes ejemplos que me delgada que podría utilizar

1

me escribió una versión recursiva, ampliada que va a clasificar por cualquier número de atributos, en orden:

//sort_xml_by_attr($simplexmlobject,array('attr_one','attr_two','attr_three')) 

    class SortXML { 
    public $xml; 
    var $attr; 
    function SortXML($xml,$attr) { 
     $this->xml = $xml; 
     $this->attr = $attr; 
    } 
    function cmp_attr($a,$b) { 
     $a1 = (string)$a->xml[(string)$a->attr]; 
     $b1 = (string)$b->xml[(string)$b->attr]; 
     if (is_numeric($a1) && is_numeric($b1)) { 
     if (is_float($a1) && is_float($b1)) { 
      $a1 = (float)$a1; 
      $b1 = (float)$b1; 
     } else { 
      $a1 = (int)$a1; 
      $b1 = (int)$b1; 
     } 
     } 
     if ($a1 == $b1) return 0; 
     return ($a1 > $b1) ? +1 : -1; 
    } 
    } 

    function sort_xml_by_attr($xml_obj,$attr) { 
    if (count($attr)>1) { 
     // break up array by unique values of the first attribute in the list 
     $unique_attrs = array(); 
     foreach ($xml_obj as $i) $unique_attrs[] = (string)$i[$attr[0]]; 
     $unique_attrs = array_unique($unique_attrs); 
     sort($unique_attrs); 
     // create an array of arrays who share a unique attribute value 
     foreach ($unique_attrs as $i) { 
     foreach ($xml_obj as $p) { 
      if ($p[$attr[0]] == $i) $xml_arrays[$i][] = $p; 
     } 
     } 
     // remove first element to progress the recursion to the next attribute 
     array_shift($attr); 
     $new_array = array(); 
     // concatenate sorted arrays 
     foreach ($xml_arrays as $i) { 
     $new_array = array_merge($new_array,sort_xml_by_attr($i,$attr)); 
     } 
     return $new_array; 
    } else { 
     // create wrapper objects with new comparison function 
     foreach ($xml_obj as $i) $new_obj[] = new SortXML($i,$attr[0]); 
     usort($new_obj,array('SortXML','cmp_attr')); 
     foreach ($new_obj as $i) $sorted_obj[] = $i->xml; 
     return $sorted_obj; 
    } 
    } 
15

Para referencia futura, esto es algo que se puede utilizar para consultar los nodos a través de XPath y ordenar el resultado a través de XPath también: SimpleDOM. En este ejemplo, en cierto modo me <tree/> todos los nodos de valores del atributo order:

include 'SimpleDOM.php'; 

$page = simpledom_load_string('<page> 
    <talentTrees> 
     <tree name="Football" order="2"/> 
     <tree name="Baseball" order="0"/> 
     <tree name="Frisbee" order="1"/> 
    </talentTrees> 
</page>'); 

$nodes = $page->sortedXPath('//tree', '@order'); 

foreach ($nodes as $node) 
{ 
    echo $node->asXML(), "\n"; 
} 
+0

Esto funciona genial. Tuve que mirar esto un tiempo para darme cuenta de que SimpleDOM debe descargarse como una inclusión. – Aaron

+0

Incluyo SimpleDom.php pero el sistema aún no se da cuenta del método sortedXPath, ¿por qué? – budamivardi

+0

@budamivardi debe estar usando simplexml_load_string en lugar de simpledom_load_string, o simplexml_load_file en lugar de simpledom_load_file –

0

Si tiene muchos elementos de este tipo

$string = <<<EOS 
<page> 
<talentTrees> 
<tree name="Football" order="2" /> 
<tree name="Baseball" order="0" /> 
<tree name="Frisbee" order="1" /> 
</talentTrees> 
<talentTrees> 
<tree name="Football2" order="1" /> 
<tree name="Baseball2" order="2" /> 
<tree name="Frisbee2" order="0" /> 
</talentTrees> 
</page> 
EOS; 

Puede utilizar foreach:

$xml = simplexml_load_string($string); 

function sort_trees($t1, $t2) { 
    return $t1['order'] - $t2['order']; 
} 

foreach($xml->talentTrees as $talentTrees){ 
    foreach($talentTrees->tree as $tree){ 
    $trees[]= $tree; 
    } 
    usort($trees, 'sort_trees'); 
    print_r($trees); 
    unset($trees); 
} 

de salida:

Array 
(
    [0] => Array 
     (
      [0] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Baseball 
          [order] => 0 
         ) 

       ) 

      [1] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Frisbee 
          [order] => 1 
         ) 

       ) 

      [2] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Football 
          [order] => 2 
         ) 

       ) 

     ) 

    [1] => Array 
     (
      [0] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Frisbee2 
          [order] => 0 
         ) 

       ) 

      [1] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Football2 
          [order] => 1 
         ) 

       ) 

      [2] => SimpleXMLElement Object 
       (
        [@attributes] => Array 
         (
          [name] => Baseball2 
          [order] => 2 
         ) 

       ) 

     ) 

) 

Para otro ejemplo: https://stackoverflow.com/a/44379495/3506219

Cuestiones relacionadas