【问题标题】:Sort XML via attribute value PHP通过属性值 PHP 对 XML 进行排序
【发布时间】:2010-11-24 11:00:50
【问题描述】:

所以我有一个 XML 文件,我试图根据属性“order”按顺序循环。

这是一个例子:

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

我的目标是使用 foreach 遍历每个“树”,但我想按照 order 属性的顺序读取它们:棒球、飞盘、足球。 (0,1,2)。

抱歉英语不好,不是我的母语。

【问题讨论】:

    标签: php xml simplexml


    【解决方案1】:

    This page 给出了一些我认为你可以使用的很好的例子

    【讨论】:

      【解决方案2】:

      这应该会给你你想要的:

      $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 现在按 order 属性排序。

      【讨论】:

      • 当数字大于 9 时会失败。它会像这样排序:1、100、2、245、300、4。而不是 1、2、4、100、245、300。使用乔什戴维斯的建议如下。效果很好。
      【解决方案3】:

      我写了一个递归的扩展版本,它将按任意数量的属性排序:

      //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;
          }
        }
      

      【讨论】:

        【解决方案4】:

        为了将来参考,您可以使用以下内容通过 XPath 查询节点并通过 XPath 对结果进行排序:SimpleDOM。在此示例中,我按 order 属性的值对所有 &lt;tree/&gt; 节点进行排序:

        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";
        }
        

        【讨论】:

        • 这很好用。我看了一会儿才意识到 SimpleDOM 需要作为包含下载。
        • 我包含了SimpleDom.php但是系统仍然没有实现sortedXPath方法,为什么?
        • @budamivardi 您必须使用 simplexml_load_string 而不是 simpledom_load_string,或 simplexml_load_file 而不是 simpledom_load_file
        【解决方案5】:

        我得到了使用PHP中的属性进行xml排序的解决方案。

        请访问以下网址:-

        http://ewebsurf.blogspot.com/2010/12/xml-sorting-using-attributes-php.html

        【讨论】:

          【解决方案6】:

          如果你有很多这样的元素

          $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;
          

          你可以使用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);
          }
          

          输出:

          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
                                  )
          
                          )
          
                  )
          
          )
          

          再举个例子:https://stackoverflow.com/a/44379495/3506219

          【讨论】:

            猜你喜欢
            • 2020-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-08-30
            • 2022-01-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多