2014-05-07 62 views
1

命名的鍵(不是數字鍵)陣列,但我想它們被命名爲鍵而不是數字。使用SimpleXML解析XML文件,並創建使用我已經從解析的XML文件中使用帶數字鍵的SimpleXML創建多維數組PHP

XML文件如下:

<workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" > 
<Worksheet ss:Name="tab1"> 
<Table> 
    <Row> 
     <Cell><Data>Id</Data></Cell> // names which i want to be array keys. 
     <Cell><Data>Company</Data></Cell> // 
     <Cell><Data>Year</Data></Cell> // 
    </Row> 
    <Row> 
     <Cell><Data>120</Data></Cell> //values 
     <Cell><Data>Apple</Data></Cell> 
     <Cell><Data>2011</Data></Cell> 
    </Row> 
    <Row> 
     <Cell><Data>121</Data></Cell> 
     <Cell><Data>Samsung</Data></Cell> 
     <Cell><Data>2010</Data></Cell> 
    </Row> 
</Table> 
</Worksheet> 
<Worksheet ss:Name="tab2"> 
<Table> 
    <Row> 
     <Cell><Data>Id</Data></Cell>  
     <Cell><Data>Company</Data></Cell> 
     <Cell><Data>Year</Data></Cell> 
    </Row> 
    <Row> 
     <Cell><Data>320</Data></Cell> 
     <Cell><Data>Sony</Data></Cell> 
     <Cell><Data>2001</Data></Cell> 
    </Row> 
    <Row> 
     <Cell><Data>321</Data></Cell> 
     <Cell><Data>HTC</Data></Cell> 
     <Cell><Data>2001</Data></Cell> 
    </Row> 
    </Table> 
</Worksheet> 
</workbook> 

她是我的解析XML文件,並創建陣列

$xml=simplexml_load_file($fileData); 
$result= array(); 
$i=0; 
foreach($xml->Worksheet as $worksheet): 
    $result['tab'][$i] = array(); 
    $result['tab'][$i]['name']=(string)$worksheet->attributes("ss", true)->Name; 
    foreach($worksheet as $table): 
    $k =0; 
    unset($table->Row[0]); //removing first row which i want to be keys of array 
    foreach($table as $row): 
     foreach($row as $cell): 
     $result['tab'][$i]['data'][$k][] =(string)$cell->Data; 
     endforeach; 
     $k++; 
    endforeach; 
    endforeach; 
    $i++; 
endforeach; 
return $result; 

數組,我得到的代碼:

Array 
    (
    [tab] => Array 
    (
     [0] => Array 
      (
       [name] => tab1 
       [data] => Array 
        (
         [0] => Array 
          (
           [0] => 120 //keys should be name of first row of xml 
           [1] => Apple 
           [2] => 2011 
          ) 

         [1] => Array 
          (
           [0] => 121 
           [1] => Samsung 
           [2] => 2010 
          ) 

        ) 

      ) 

     [1] => Array 
      (
       [name] => tab2 
       [data] => Array 
        (
         [0] => Array 
          (
           [0] => 320 
           [1] => Sony 
           [2] => 2001 
          ) 

         [1] => Array 
          (
           [0] => 321 
           [1] => HTC 
           [2] => 2001 
          ) 

        ) 

      ) 

    ) 

) 

我想排列如下:

Array 
(
    [tab] => Array 
    (
     [0] => Array 
      (
       [name] => tab1 
       [data] => Array 
        (
         [0] => Array 
          (
           [Id] => 120   // named keys instead of numbers 
           [Company] => Apple 
           [Year] => 2011 
          ) 

         [1] => Array 
          (
           [Id] => 121 
           [Company] => Samsung 
           [Year] => 2010 
          ) 

        ) 

      ) 

     [1] => Array 
      (
       [name] => tab2 
       [data] => Array 
        (
         [0] => Array 
          (
           [Id] => 320 
           [Company] => Sony 
           [Year] => 2001 
          ) 

         [1] => Array 
          (
           [Id] => 321 
           [Company] => HTC 
           [Year] => 2001 
          ) 

        ) 

      ) 

    ) 

這是一個有點長的問題。但很好解釋。 謝謝。

回答

3

轉換每個錶行到一個數組,然後使用該第一行作爲鍵用於隨後的行:

$table_to_array = function(SimpleXMLElement $table) { 
    $keyed = function($table) { 
     $keys = NULL; 
     foreach ($table->Row as $row) { 
      $array = array_map('trim', $row->xpath('Cell/Data')); 
      $keys ? (yield array_combine($keys, $array)) 
       : $keys = $array; 
     } 
    }; 
    return iterator_to_array($keyed($table)); 
}; 

$xml = simplexml_load_file($path_to_xml_file); 

$array = $table_to_array($xml->Worksheet->Table); 

print_r($array); 

輸出:

Array 
(
    [0] => Array 
     (
      [Id] => 120 
      [Company] => Apple 
      [Year] => 2011 
     ) 

    [1] => Array 
     (
      [Id] => 121 
      [Company] => Samsung 
      [Year] => 2010 
     ) 

) 

應用此到儘可能多的表作爲你喜歡。


如果你有PHP < 5.5,那麼你不能使用發電機然而,迄今爲止,你仍然可以使用的迭代器。這或多或少只是意味着你需要寫更多的代碼:

// this example uses some code from: 
// https://github.com/hakre/Iterator-Garden/blob/master/src/IndexIteration.php 
require_once 'IndexIteration.php'; 

class TableRowIterator extends IteratorIterator 
{ 
    public function __construct(SimpleXMLElement $table) { 
     parent::__construct(new IndexIteration($table->Row)); 
    } 

    public function current() { 
     return array_map('trim', parent::current()->xpath('Cell/Data')); 
    } 

    public function key() { 
     return $this->getInnerIterator()->getIndex(); 
    } 
} 

class KeyedArrayIterator extends IteratorIterator 
{ 
    private $keys; 

    public function rewind() 
    { 
     parent::rewind(); 
     $this->keys = parent::current(); 
     parent::next(); 
    } 

    public function current() 
    { 
     return array_combine($this->keys, parent::current()); 
    } 
} 

$table_to_array = function($table) { 
    $rows = new TableRowIterator($table); 
    $keyed = new KeyedArrayIterator($rows); 
    return iterator_to_array($keyed); 
}; 

$xml = simplexml_load_file($path_to_xml_file); 

$array = $table_to_array($xml->Worksheet->Table); 

print_r($array); 

,因爲它表明,一些代碼多行,但以同樣的方式來處理數據。比較KeyedArrayIteratorthe commented answer中的CSVFile Iterator類,就是這種處理方式:使用第一行作爲所有後續行的鍵。

的輸出是完全一樣與發電機的PHP 5.5例子。

+0

哇,關閉創建發生器產生array_combine和iterator_to_array :) – pce

+0

謝謝! [我對這個問題的回答*使用列標題處理CSV到數組中的關鍵*](http://stackoverflow.com/a/10181302/367456)顯示,一旦設法將每行轉換爲數組,它也適用於5.5以下的PHP,因此封閉和發生器少。以防其他方式寫下來。這也是這個想法的來源,這裏的問題讓我想起了那個。 – hakre

+0

它不適用於PHP 5.4.19。 – nohan