SimpleXML
在线手册:中文 英文
PHP手册

The SimpleXMLIterator class

(PHP 5 >= 5.1.0)

简介

The SimpleXMLIterator provides recursive iteration over all nodes of a SimpleXMLElement object.

类摘要

SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator , Traversable , Iterator , Countable {
/* 方法 */
public mixed current ( void )
SimpleXMLIterator getChildren ( void )
bool hasChildren ( void )
mixed key ( void )
void next ( void )
void rewind ( void )
bool valid ( void )
/* 继承的方法 */
final public SimpleXMLElement::__construct ( string $data [, int $options = 0 [, bool $data_is_url = false [, string $ns = "" [, bool $is_prefix = false ]]]] )
public void SimpleXMLElement::addAttribute ( string $name [, string $value [, string $namespace ]] )
public SimpleXMLElement SimpleXMLElement::addChild ( string $name [, string $value [, string $namespace ]] )
public mixed SimpleXMLElement::asXML ([ string $filename ] )
public SimpleXMLElement SimpleXMLElement::attributes ([ string $ns = NULL [, bool $is_prefix = false ]] )
public SimpleXMLElement SimpleXMLElement::children ([ string $ns [, bool $is_prefix = false ]] )
public int SimpleXMLElement::count ( void )
public array SimpleXMLElement::getDocNamespaces ([ bool $recursive = false ] )
public string SimpleXMLElement::getName ( void )
public array SimpleXMLElement::getNamespaces ([ bool $recursive = false ] )
public bool SimpleXMLElement::registerXPathNamespace ( string $prefix , string $ns )
public array SimpleXMLElement::xpath ( string $path )
}

Table of Contents


SimpleXML
在线手册:中文 英文
PHP手册
PHP手册 - N: The SimpleXMLIterator class

用户评论:

Gordon (21-Mar-2012 10:53)

A few small changes to ratfactor's code to allow for better key->value pairs (when no children) and also allow for attributes.
class xmlit {
    function xml2array($xml){
        $sxi = new SimpleXmlIterator($xml);
        return $this->sxiToArray($sxi);
    }

    /**
     * @param SimpleXMLIterator $sxi
     * @return array
     */
    function sxiToArray($sxi){
        $a = array();
        $attribs = (array)$sxi->attributes();
        if($attribs) {
            $a = $attribs;
        }
        for( $sxi->rewind(); $sxi->valid(); $sxi->next() ) {
            if(!array_key_exists($sxi->key(), $a)){
                $a[$sxi->key()] = array();
            }
            if($sxi->hasChildren()){
                $a[$sxi->key()][] = $this->sxiToArray($sxi->current());
            }
            else{
                if($sxi->current()->attributes()) {
                    $a[$sxi->key()] = $this->sxiToArray($sxi->current());
                    $a[$sxi->key()]['value'] = strval($sxi->current());
                } else {
                    $a[$sxi->key()] = strval($sxi->current());
                }
            }
        }
        return $a;
    }
}

ajnsit dot NOSPAM at gmail dot com (17-Mar-2011 06:14)

Here's a simple function to convert an XML string to an array -

<?php
// PHP5.3 and above only
function parse($str) {
   
$f = function($iter) {
      foreach(
$iter as $key=>$val)
       
$arr[$key][] = ($iter->hasChildren())?
         
call_user_func (__FUNCTION__, $val)
          :
strval($val);
      return
$arr;
    };
    return
$f(new SimpleXmlIterator($str, null));
}
?>

PHP 5.2 and below do not have anonymous functions.
But you can create a helper function to achieve the same thing -

<?php
 
function parse($str) {
    return
parseHelper(new SimpleXmlIterator($str, null));
  }
  function
parseHelper($iter) {
    foreach(
$iter as $key=>$val)
     
$arr[$key][] = ($iter->hasChildren())?
       
call_user_func (__FUNCTION__, $val)
        :
strval($val);
    return
$arr;
  }
?>

Using it is straightforward enough -

<?php

$xml
= '
<movies>
  <movie>abcd</movie>
  <movie>efgh</movie>
  <movie>hijk</movie>
</movies>'
;
var_dump(parse($xml));

?>

This will output -

array
  'movie' =>
    array
      0 => string 'abcd' (length=4)
      1 => string 'efgh' (length=4)
      2 => string 'hijk' (length=4)

ratfactor at gmail dot com (20-Jul-2009 01:08)

The documentation is a bit sparse for SimpleXmlIterator.  Here is an example showing the use of its methods. xml2Array and sxiToArray work together to convert an XML document to an associative array structure.

The contents of cats.xml:
======================================
<cats>
  <cat>
      <name>Jack</name>
      <age>2</age>
      <color>grey</color>
      <color>white</color>
  </cat>
  <cat>
      <name>Maxwell</name>
      <age>12</age>
      <color>orange</color>
      <color>black</color>
  </cat>
</cats>
======================================

<?php
function xml2array($fname){
 
$sxi = new SimpleXmlIterator($fname, null, true);
  return
sxiToArray($sxi);
}

function
sxiToArray($sxi){
 
$a = array();
  for(
$sxi->rewind(); $sxi->valid(); $sxi->next() ) {
    if(!
array_key_exists($sxi->key(), $a)){
     
$a[$sxi->key()] = array();
    }
    if(
$sxi->hasChildren()){
     
$a[$sxi->key()][] = sxiToArray($sxi->current());
    }
    else{
     
$a[$sxi->key()][] = strval($sxi->current());
    }
  }
  return
$a;
}

// Read cats.xml and print the results:
$catArray = xml2array('cats.xml');
print_r($catArray);
?>

Results (reformatted a bit for compactness and clarity):
======================================
Array(
  [cat] => Array(
    [0] => Array(
      [name] => Array(  [0] => Jack    )
      [age] => Array(   [0] => 2       )
      [color] => Array( [0] => grey,
                        [1] => white   )
    )
    [1] => Array(
      [name] => Array(  [0] => Maxwell )
      [age] => Array(   [0] => 12      )
      [color] => Array( [0] => orange
                        [1] => black   )
    )
  )
)

David Lanstein (18-Jan-2009 02:40)

Unlike the DirectoryIterator, for one, you'll need to call $it->rewind() before using the iterator in a for() or while() loop.  Calling foreach() does rewind the iterator before iteration.