2014-05-07 34 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