文字

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 , Countable {
public mixed current ( void )
public SimpleXMLIterator getChildren ( void )
public bool hasChildren ( void )
public mixed key ( void )
public void next ( void )
public void rewind ( void )
public 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 [, bool $from_root = true ]] )
public string SimpleXMLElement::getName ( void )
public array SimpleXMLElement::getNamespaces ([ bool $recursive = false ] )
public bool SimpleXMLElement::registerXPathNamespace ( string $prefix , string $ns )
public string SimpleXMLElement::__toString ( void )
public array SimpleXMLElement::xpath ( string $path )
}

Table of Contents

  • SimpleXMLIterator::current — Returns the current element
  • SimpleXMLIterator::getChildren — Returns the sub-elements of the current element
  • SimpleXMLIterator::hasChildren — Checks whether the current element has sub elements.
  • SimpleXMLIterator::key — Return current key
  • SimpleXMLIterator::next — Move to next element
  • SimpleXMLIterator::rewind — Rewind to the first element
  • SimpleXMLIterator::valid — Check whether the current element is valid

用户评论:

[#1] php-lover at live dot com [2015-10-05 21:50:34]

Function to extract SimpleXMLElement data to array.

function extract($sxe = null) {
if (!$sxe instanceOf SimpleXMLElement)
return array();

$extract = array();

foreach ($sxe->children() as $key => $value) {
if (array_key_exists($key, $extract)) {
if (!isset($extract[$key][0])) {
$tmp_extract = $extract[$key];
$extract[$key] = array();
$extract[$key][0] = $tmp_extract; 
} else
$extract[$key] = (array) $extract[$key];


if ($value->count()) {
if (isset($extract[$key]) && is_array($extract[$key]))
$extract[$key][] = $this->extract($value);
else
$extract[$key] = $this->extract($value);
} else {
if (isset($extract[$key]) && is_array($extract[$key]))
$extract[$key][] = empty(strval($value)) ? null : strval($value);
else
$extract[$key] = empty(strval($value)) ? null : strval($value);
}
}

return $extract;
}

[#2] centy2010 at hotmail dot com [2014-07-16 03:22:10]

I filled my database from an XML file about 1260 Kb.
I made my process less than a second. Simply by using SimpleXML.

I give you a little example of the usage to fill a database.
Given the table universe.
With 4 columns Coords, Planet_Name, Player_id, Moon_Size.

Now You have a XML file named universe.xml with this kind of data.
I enclose the data within php tags but it's a file :p
<?php
$xml 
= <<<EOT
<?xml version="1.0" encoding="UTF-8"?>

<universe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -
xsi:noNamespaceSchemaLocation="http://s127-fr.ogame.gameforge.com/api/xsd/universe.xsd" -
timestamp="1405413350" serverId="fr127">
<planet id="1" player="1" name="Arakis" coords="1:1:2">
<moon id="2" name="Mond" size="4998"/>
</planet>
<planet id="33620176" player="100000" name="GameAdmin" coords="1:1:3"/>
<planet id="33620179" player="100003" name="Heimatplanet" coords="1:1:1"/>
<planet id="33620186" player="100004" name="OGame Team" coords="6:250:1"/>
<planet id="33620242" player="100058" name="KnS" coords="9:1:6">
<moon id="33668391" name="Lune" size="8831"/>
</planet>
</universe>
EOT;
?>

Now how to bring these data in my 4 columns table :

<?php
$newfname 
$path."Universe.XML";
$mydata = new SimpleXmlIterator($newfname0true);
$myquery "INSERT INTO `".$tablename."` (`coords`,`planet_name`, `player_id`, `moon_size`) VALUES ";
for (
$mydata->rewind();$mydata->valid();$mydata->next()) {
    
$myquery.= " ('".$mydata->current()->attributes()['coords']
_."','".utf8_decode($mydata->current()->attributes()['name'])
_."','".utf8_decode($mydata->current()->attributes()['player'])
_."','";
    if (
$mydata->haschildren()) {
        
$myquery.= $mydate->current()->children()->attributes()['size']."'),";
    } else {
        
$myquery.= "'),";
    }
}
$myquery rtrim($myquery",");
$datatosql mysql_query($myquery);
?>

[#3] hezll at msn dot com [2013-04-11 04:34:14]

Most of the time we need to convert the XML to array or JSON , but now I have to completed the requirement of converting XML to XPath which make our template easily geting the data from XML data source due to the Xpath mapping .Here is the function:

<?php

function sxiToXpath($sxi$key null, &$tmp null)
{
    
$keys_arr = array();
    
//get the keys count array
    
for ($sxi->rewind(); $sxi->valid(); $sxi->next())
    {
        
$sk $sxi->key();
        if (
array_key_exists($sk$keys_arr))
        {
            
$keys_arr[$sk]+=1;
            
$keys_arr[$sk] = $keys_arr[$sk];
        }
        else
        {
            
$keys_arr[$sk] = 1;
        }
    }
    
//create the xpath 
    
for ($sxi->rewind(); $sxi->valid(); $sxi->next())
    {
        
$sk $sxi->key();
        if (!isset($
$sk))
        {
            $
$sk 1;
        }
        if (
$keys_arr[$sk] >= 1)
        {
            
$spk $sk '[' . $$sk ']';
            
$keys_arr[$sk] = $keys_arr[$sk] - 1;
            $
$sk++;
        }
        else
        {
            
$spk $sk;
        }
        
$kp $key $key '/' $spk '/' $sxi->getName() . '/' $spk;
        if (
$sxi->hasChildren())
        {
            
sxiToXpath($sxi->getChildren(), $kp$tmp);
        }
        else
        {
            
$tmp[$kp] = strval($sxi->current());
        }
        
$at $sxi->current()->attributes();
        if (
$at)
        {
            
$tmp_kp $kp;
            foreach (
$at as $k => $v)
            {
                
$kp .= '/@' $k;
                
$tmp[$kp] = $v;
                
$kp $tmp_kp;
            }
        }
    }
    return 
$tmp;
}

function 
xmlToXpath($xml)
{
    
$sxi = new SimpleXmlIterator($xml);
    return 
sxiToXpath($sxi);
}


$xml = <<<EOT
<?xml version="1.0" encoding="utf8" ?>
        
<data>
   <item ID="30001">
      <Company>Navarro Corp.</Company>
   </item>
   <item ID="30002" IDd="30002">
      <Company>Performant Systems</Company>
   </item>
   <item ID="30003">
      <Company id='id_test'><g id='id_g'>glove</g></Company>    
   </item>
    <item>
    </item>
</data>
EOT;

$rs = xmlToXpath($xml);
print_r($rs);



echo "Total:" . count($rs);

echo "<hr>";

$xml = new SimpleXMLElement($xml);
foreach ($rs as $k => $v)
{
    echo "Xpath:" . $k . " |Value:" . $v . " ";
    var_dump($xml->xpath($k));
    echo "<br>";
}

[#4] ajnsit dot NOSPAM at gmail dot com [2011-03-17 10:14:57]

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($strnull));
}
?>


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($strnull));
  }
  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)

[#5] ratfactor at gmail dot com [2009-07-19 17:08:28]

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($fnamenulltrue);
  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   )
    )
  )
)

上一篇: 下一篇: