SimpleXMLIterator 类

(PHP 5 >= 5.1.3, PHP 7, PHP 8)

简介

SimpleXMLIterator 提供对 SimpleXMLElement 对象的所有节点的递归迭代。

类概要

class SimpleXMLIterator extends SimpleXMLElement {
/* 继承的方法 */
public SimpleXMLElement::__construct(
    string $data,
    int $options = 0,
    bool $dataIsURL = false,
    string $namespaceOrPrefix = "",
    bool $isPrefix = false
)
public SimpleXMLElement::addAttribute(string $qualifiedName, string $value, ?string $namespace = null): void
public SimpleXMLElement::addChild(string $qualifiedName, ?string $value = null, ?string $namespace = null): ?SimpleXMLElement
public SimpleXMLElement::attributes(?string $namespaceOrPrefix = null, bool $isPrefix = false): ?SimpleXMLElement
public SimpleXMLElement::children(?string $namespaceOrPrefix = null, bool $isPrefix = false): ?SimpleXMLElement
public SimpleXMLElement::getDocNamespaces(bool $recursive = false, bool $fromRoot = true): array|false
}

变更日志

版本 描述
8.0.0 迭代器方法 (SimpleXMLIterator::hasChildren(), SimpleXMLIterator::getChildren(), SimpleXMLIterator::current(), SimpleXMLIterator::key(), SimpleXMLIterator::next(),SimpleXMLIterator::rewind(), SimpleXMLIterator::valid()) 已移至 SimpleXMLElement
8.0.0 SimpleXMLIterator 现在实现了 Stringable
添加注释

用户贡献的注释 7 个注释

ratfactor at gmail dot com
15 年前
SimpleXmlIterator 的文档有点简略。以下是一个示例,展示了其方法的使用。xml2Array 和 sxiToArray 协同工作,将 XML 文档转换为关联数组结构。

cats.xml 的内容
======================================
<cats>
<cat>
<name>Jack</name>
<age>2</age>
<color>灰色</color>
<color>白色</color>
</cat>
<cat>
<name>麦克斯韦尔</name>
<age>12</age>
<color>橙色</color>
<color>黑色</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;
}

// 读取 cats.xml 并打印结果:
$catArray = xml2array('cats.xml');
print_r($catArray);
?>

结果(为了简洁和清晰,重新格式化了一些)
======================================
数组(
[cat] => 数组(
[0] => 数组(
[name] => 数组( [0] => Jack )
[age] => 数组( [0] => 2 )
[color] => 数组( [0] => 灰色,
[1] => 白色 )
)
[1] => 数组(
[name] => 数组( [0] => 麦克斯韦尔 )
[age] => 数组( [0] => 12 )
[color] => 数组( [0] => 橙色
[1] => 黑色 )
)
)
)
hezll at msn dot com
11 年前
大多数时候我们需要将 XML 转换为数组或 JSON,但现在我必须完成将 XML 转换为 XPath 的要求,这使得我们的模板可以通过 XPath 映射轻松地从 XML 数据源中获取数据。以下函数

<?php

function sxiToXpath($sxi, $key = null, &$tmp = null)
{
$keys_arr = 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;
}
}
// 创建 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);

/**
* 结果可能像这样:
数组
(
[/data/item[1]/Company[1]] => Navarro Corp.
[/data/item[1]/@ID] => SimpleXMLIterator 对象
(
[0] => 30001
)
[/data/item[2]/Company[1]] => Performant Systems
[/data/item[2]/@ID] => SimpleXMLIterator 对象
(
[0] => 30002
)

[/data/item[2]/@IDd] => SimpleXMLIterator 对象
(
[0] => 30002
)

[/data/item[3]/Company[1]/g[1]] => glove
[/data/item[3]/Company[1]/g[1]/@id] => SimpleXMLIterator 对象
(
[0] => id_g
)

[/data/item[3]/Company[1]/@id] => SimpleXMLIterator 对象
(
[0] => id_test
)

[/data/item[3]/@ID] => SimpleXMLIterator 对象
(
[0] => 30003
)

[/data/item[4]] =>

)
*/

echo "总数:" . count($rs);

echo
"<hr>";
/* 可以像这样检查 XPath 结果 */
$xml = new SimpleXMLElement($xml);
foreach (
$rs as $k => $v)
{
echo
"XPath:" . $k . " |值:" . $v . " ";
var_dump($xml->xpath($k));
echo
"<br>";
}
centy2010 at hotmail dot com
10 年前
我从一个大约 1260 Kb 的 XML 文件中填充了我的数据库。
我将我的处理时间缩短到不到一秒。只需使用 SimpleXML。

我将提供一个使用 SimpleXML 填充数据库的小例子。
假设表名为 universe。
它有 4 列:Coords、Planet_Name、Player_id、Moon_Size。

现在你有一个名为 universe.xml 的 XML 文件,其中包含以下数据。
我将数据放在 php 标签内,但它是一个文件 :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;
?>

现在如何将这些数据导入我的 4 列表格中

<?php
$newfname
= $path."Universe.XML";
$mydata = new SimpleXmlIterator($newfname, 0, true);
$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);
?>
rukkykf at gmail dot com
5 年前
我认为值得一提的是,您需要在初始化后立即在 SimpleXMLIterator 对象上调用 rewind() 方法,然后才能对该对象执行任何其他操作。示例

<?php
$xml
= new SimpleXMLIterator('file.xml', null, true);

// 由于没有调用 rewind() 方法,因此 $x 将设置为 null
$x = $xml->current();

$xml->rewind();

// $x 将设置为第一个元素
$x = $xml->current();

?>
php-lover at live dot com
8 年前
将 SimpleXMLElement 数据提取到数组的函数。

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;
}
prouchetvincent at free dot fr
3 年前
<?php
=======================================================
$index =
<?
xml version="1.0" encoding="UTF-8"?>
<root>
<article id="8" visibility="true" filename="2020-10-08" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="7" visibility="true" filename="2020-10-07" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="6" visibility="true" filename="2020-10-02" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="5" visibility="true" filename="2020-09-30" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="4" visibility="true" filename="2020-09-26" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="3" visibility="true" filename="2020-09-22" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="2" visibility="true" filename="2020-09-20" fileExtension="xml">
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
<article id="1" visibility="true" filename="hello world" fileExtension="xml">
Hello World
<tag>xml</tag>
<tag>php</tag>
<tag>experiment</tag>
</article>
</root>
====================================================================
?>
如果您必须使用迭代器来解析您的 XML
并且需要获取此迭代器标签的属性,那么
使用函数
->current()
在您的对象上,在以下操作之前
->attributes()->{属性名称}
<?php
$file
="";
try{
$index = new SimpleXMLIterator ( file_get_contents ( FILEDIRECTORY. 'index.xml' ) );}
catch(
Exception $e) {您希望在错误发生时执行的操作}}

for(
$index->rewind(); $index->valid(); $index->next() ) {
try {
$file = file_get_contents(FILESDIRECTORY.$index->current()->attributes()->{'fileName'}. '.xml' );
} catch (
Exception $e) {您希望在错误发生时执行的操作}
$article = new Article ();
$article->setXMLArticle ($file);
array_push( $this->articles, $article );
$file ="";
}
}
?>
此示例使用自定义的 Article 对象,该对象本身解析传递给它的文件以初始化其属性。
在这里,我们打开一个文件(是的,我使用常量来表示我的目录)
将其设为 simpleXMLIterator,并解析 article 元素以获取 filename 属性,以便将其用于打开另一个 XML 文件以进行数据收集。
别忘了!!!由 new ClassName() 创建的 PHP 对象始终通过引用传递,这就是为什么 new Article() 在循环内部而不是外部的原因
(是的,我犯了那个错误)
XMLIterator 功能强大,但本身很难理解,但一旦过了那个阶段。
它们比普通数组更容易使用。
ajnsit dot NOSPAM at gmail dot com
13 年前
这是一个将 XML 字符串转换为数组的简单函数 -

<?php
// 仅适用于 PHP5.3 及更高版本
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 及更低版本没有匿名函数。
但是您可以创建一个辅助函数来实现相同的功能 -

<?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;
}
?>

使用它非常简单 -

<?php

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

?>

这将输出 -

数组
'movie' =>
数组
0 => 字符串 'abcd' (长度为 4)
1 => 字符串 'efgh' (长度为 4)
2 => 字符串 'hijk' (长度为 4)
To Top