multidimensional array迭代

假设你有以下数组:

$nodes = array( "parent node", "parent node", array( "child node", "child node", array( "grand child node", "grand child node"))); 

你将如何将其转换为XMLstring,使其看起来像:

 <node> <node>parent node</node> <node>parent node</node> <node> <node>child node</node> <node>child node</node> <node> <node>grand child node</node> <node>grand child node</node> </node> </node> </node> 

一种方法可以通过recursion方法来实现:

 function traverse($nodes) { echo "<node>"; foreach($nodes as $node) { if(is_array($node)) { traverse($node); } else { echo "<node>$node</node>"; } } echo "</node>"; } traverse($nodes); 

不过,我正在寻找一种使用迭代的方法。

 <?php $nodes = array( "parent node", "parent node", array( "child node", "child node", array( "grand child node", "grand child node" ) ) ); $s = '<node>'; $arr = $nodes; while(count($arr) > 0) { $n = array_shift($arr); if(is_array($n)) { array_unshift($arr, null); $arr = array_merge($n, $arr); $s .= '<node>'; } elseif(is_null($n)) $s .= '</node>'; else $s .= '<node>'.$n.'</node>'; } $s .= '</node>'; echo $s; ?> 

您可以使用迭代器迭代数组,然后生成所需的输出:

 class TranformArrayIterator extends RecursiveIteratorIterator { protected function indent() { echo str_repeat("\t", $this->getDepth()); return $this; } public function beginIteration() { echo '<nodes>', PHP_EOL; } public function endIteration() { echo '</nodes>', PHP_EOL; } public function beginChildren() { $this->indent()->beginIteration(); } public function endChildren() { $this->indent()->endIteration(); } public function current() { return sprintf('%s<node>%s</node>%s', str_repeat("\t", $this->getDepth() +1), parent::current(), PHP_EOL); } } 

然后像这样组装:

 $iterator = new TranformArrayIterator(new RecursiveArrayIterator($nodes)); foreach($iterator as $val) { echo $val; } 

输出

 <nodes> <node>parent node</node> <node>parent node</node> <nodes> <node>child node</node> <node>child node</node> <nodes> <node>grand child node</node> <node>grand child node</node> </nodes> </nodes> </nodes> 

在使用$key => $val时将$key => $val清空,将其添加到TraverseArrayIterator

 public function key() { return ''; } 

由于您的目标似乎是生成XML,您还可以将XMLWriter作为协作者传递给Iterator。 这允许更多的控制生成的XML,并确保输出是有效的XML:

 class TranformArrayIterator extends RecursiveIteratorIterator { private $xmlWriter; public function __construct( XmlWriter $xmlWriter, Traversable $iterator, $mode = RecursiveIteratorIterator::LEAVES_ONLY , $flags = 0) { $this->xmlWriter = $xmlWriter; parent::__construct($iterator, $mode, $flags); } public function beginIteration() { $this->xmlWriter->startDocument('1.0', 'utf-8'); $this->beginChildren(); } public function endIteration() { $this->xmlWriter->endDocument(); } public function beginChildren() { $this->xmlWriter->startElement('nodes'); } public function endChildren() { $this->xmlWriter->endElement(); } public function current() { $this->xmlWriter->writeElement('node', parent::current()); } } 

然后你可以像这样使用它:

 $xmlWriter = new XmlWriter; $xmlWriter->openUri('php://output'); $xmlWriter->setIndent(true); $xmlWriter->setIndentString("\t"); $iterator = new TranformArrayIterator( $xmlWriter, new RecursiveArrayIterator($nodes) ); 

然后foreach '它会产生相同的输出(然后添加XML序言)