2024 年 PHP 日本大会

SimpleXML 函数

目录

添加笔记

用户贡献笔记 37 条笔记

help :-) @ theapotek :-) com
13 年前
如果您在访问 SimpleXML 文档中的 CDATA 时遇到问题,则无需在使用 simplexml 加载之前使用 str_replace/preg_replace 删除 CDATA。

您可以这样做,所有 CDATA 内容都将作为字符串合并到元素内容中。

$xml = simplexml_load_file($xmlfile,
'SimpleXMLElement', LIBXML_NOCDATA);
cmsa at gmx dot de
17 年前
我在实体方面遇到问题。

我的第一个解决方案
我这样保存数据
$ENTRY_->
addchild('Nachricht',htmlentities($_POST["blog"]));

XML 文件中包含这样的实体
<!ENTITY auml "&amp;auml">

我这样加载数据
html_entity_decode($ENTRY->Nachname);

但是保存和
加载 xml 文件后,实体条目
<!ENTITY auml "&amp;auml">
消失了。奇怪...

我的第二个解决方案
我这样保存数据
$ENTRY_->
addchild('Nachricht',htmlentities(htmlentities($_POST["blog"])));

我现在可以使用 html_entity_decode 加载它,而无需
XML 文件中的实体条目!
我用 äöü 测试过。

希望对您有所帮助。
joel [from the website] purerave.com
17 年前
这里没有任何地方提到这一点,但是从无效字符串创建新的 SimpleXMLElement 对象会引发异常。它在 php 日志中看起来很丑,因为它在多行中转储堆栈。

创建新的 SimpleXMLElement 对象的正确方法如下所示
<?php
$xmlstr
= ''; // 空字符串会引发异常
try {
$xml = new SimpleXMLElement($xmlstr);
} catch (
Exception $e) {
// 处理错误
echo '$xmlstr 不是有效的 xml 字符串';
}
?>
brcavanagh AT NO SPAM hotmail.com
19 年前
如果您想将 SimpleXML 用于读取 XML 文档以外的任何用途,则应认真考虑并使用 XML DOM 库。当您在 DOM 中实现足够的实用程序来处理 SimpleXML 中的所有挫折时,您将违背使用 SimpleXML 的目的。原因如下,并且已经有很多解决方法,但主要问题是

1) 没有复杂的节点赋值。您不能切换节点或替换它们。

2) 没有追加新子节点

3) 每当您执行类似 $new_node = $xml_doc->node 的操作时,即使您使用克隆方法,您也将始终获得引用,这将导致脚本崩溃。

除此之外,它是一个读取文档的好工具。
r dot m dot 0100101 at gmail dot com
11 年前
这是对 https://php.net/manual/en/ref.simplexml.php#103617 函数的略微调整。
他们提供的函数会将 simpleXML 转换为数组,但仅限于最高级别。一旦您使用 is_object 添加 is_array 检查,它应该将每一级都转换为数组(至少对我来说,它转换了三级)。

function simpleXmlObjectToArray ( $xmlObject, $out = array () )
{
foreach ( (array) $xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) || is_array($node) )
? simpleXmlObjectToArray ( $node )
: $node;

return $out;
}
快乐编码!
William Fahria
11 年前
一个简单的实现
您可以将文本格式的直接 XML 传递给函数。

function eoXML2Array($xmlContent, $out = array()){
$xmlObject = is_object($xmlContent) ? $xmlContent : simplexml_load_string($xmlContent);
foreach((array) $xmlObject as $index => $node)
$out[$index] = ( is_object($node) || is_array($node) ) ? eoXML2Array( $node ) : $node;
return $out;
}

用法:$your_array = eoXML2Array(你的xml文本);
paul at preinheimer dot com
19 年前
你好,

如果您想访问名称中带有破折号的元素(这在国会图书馆以及 NWS 提供的 XML 文档中很常见),则需要以略微不同的方式处理它。

您可以使用 XPATH,它运行良好,但每次都会返回结果数组,即使只有一个结果。
例如。

<?php
$xml
->xpath('/data/time-layout/start-valid-time');
?>

您也可以选择只封装包含破折号的元素名称
<?php $xml->data->{'time-layout'}->{'start-valid-time'} ?>

--

在一个仅部分相关的说明中,处理 SimpleXML 是我唯一一次使用 PHP 进行强制转换的时候。在遍历(foreach)有效时间时,回显元素效果很好(它只是回显了相应的时间),将其分配给另一个变量会导致包含要分配时间的 SimpleXML 对象,而不是时间本身。这是通过将时间强制转换为字符串来解决的

<?php
foreach($xml->data->{'time-layout'}->{'start-valid-time'} AS $time)
{
$weatherDates[] = (string) $time;
}
?>
brandonkirsch at gmail dot com
11 年前
与这里发布的其他注释相反,SimpleXML *不会*正确处理非 UTF8 编码的 XML 文档。

使用扩展字符(即大于 127 的字节值)时,在 PHP 5.2.17 或 5.5.1 中,声明和编码为“iso-8859-1”的正确 XML 文档不会使用 SimpleXML 解析。

另一方面,DOMDocument 将正确解析传入的 iso-8859-1 XML 文档,还可以用于执行字符转换到 UTF8

$dom = new DOMDocument();

if($dom->loadXML($fileContents)){ // $fileContents 是一个在声明中指定了 iso-8859-1 编码的 XML 文档
$dom->encoding = 'utf-8'; // 将文档编码转换为 UTF8
return $dom->saveXML(); // 返回有效的 utf8 编码的 XML
andrvm
16 年前
<?php
/**
* 使用XPath移除节点/多个节点
*
* @param SimpleXMLElement $xml
* @param string XPath $path
* @param string ('one'|'child'|'all') $multi
*
* 用法:
*
* 示例XML文件 - http://ru2.php.net/manual/ru/ref.simplexml.php
*
* $xml = simplexml_load_file($xmlfile);
*
* //1. 只移除一个节点(无子节点)
* // $path 必须返回唯一的一个无子节点的节点
* removeNode($xml, '//movie/rating[@type="thumbs"]');
*
* //2. 移除一个节点(含一个子节点)
* // $path 可以返回任何节点 - 只会移除第一个节点及其所有子节点
* removeNode($xml, '//characters', 'child')
*
* //3. 移除所有节点(含子节点)
* // $path 可以返回任何节点 - 会移除所有节点及其所有子节点
* removeNode($xml, '//rating', 'all')
*
* $xml->asXML($xmlfile);
*
*/
function removeNode($xml, $path, $multi='one')
{
$result = $xml->xpath($path);

// 错误的 $path
if (!isset($result[0])) return false;

switch (
$multi) {
case
'all':
$errlevel = error_reporting(E_ALL & ~E_WARNING);
foreach (
$result as $r) unset ($r[0]);
error_reporting($errlevel);
return
true;

case
'child':
unset(
$result[0][0]);
return
true;

case
'one':
if (
count($result[0]->children())==0 && count($result)==1) {
unset(
$result[0][0]);
return
true;
}

default:
return
false;
}
}
?>

补充说明:使用后(如果删除了所有节点)
<?php

function trimXml($xmlfile)
{
$dom = new DOMDocument();

$dom->preserveWhiteSpace = false;

if (!
$dom->load($xmlfile)) return false;

$dom->formatOutput = true;

if (!
$dom->save($xmlfile)) return false;

return
true;
}
?>
T CHASSAGNETTE t_chassagnette at yahoo dot fr
19 年前
另一种基于Daniel FAIVRE的灵感,将XML文档解析为PHP数组的SimpleXML方法!

<?php
function xml2php($xml)
{
$fils = 0;
$tab = false;
$array = array();
foreach(
$xml->children() as $key => $value)
{
$child = xml2php($value);

// 处理属性
foreach($node->attributes() as $ak=>$av)
{
$child[$ak] = (string)$av;

}

// 查看新子节点是否已存在于数组中
if($tab==false && in_array($key,array_keys($array)))
{
// 如果此元素已存在于数组中,我们将创建一个索引数组
$tmp = $array[$key];
$array[$key] = NULL;
$array[$key][] = $tmp;
$array[$key][] = $child;
$tab = true;
}
elseif(
$tab == true)
{
// 将元素添加到现有数组中
$array[$key][] = $child;
}
else
{
// 添加简单元素
$array[$key] = $child;
}

$fils++;
}


if(
$fils==0)
{
return (string)
$xml;
}

return
$array;

}
?>
ngkongs at gmail dot com
16 年前
修复了我之前发布的函数,引号位置错误

function implode2($glue="", $var){
if ($var){
foreach ($var as $value){
$array[]=strval($value);
}
return implode($glue, $array);
}
else return false;
}
Eric
11 年前
如果SimpleXMLObject包含数组,添加is_array()允许函数继续查找对象。

<?php
function xml2array ( $xmlObject, $out = array () )
{
foreach ( (array)
$xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) || is_array ( $node ) ) ? xml2array ( $node ) : $node;

return
$out;
}
?>
Douglas Marsh
15年前
SimpleXML 对于将XML数据加载/转换为原生PHP数据结构非常有用。我正在考虑对SVG进行粗略搜索以查找宽度/高度,因为它实际上是一个XML文件……我发现了一种超级简单的解析我想要的信息的方法

<?php
// 为提高可读性,内联不完整的SVG数据
$RawXML = <<< XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://www.example.com/dc"
xmlns:cc="http://www.example.com/cc"
xmlns:rdf="http://www.example.com/rdf"
xmlns:svg="http://www.example.com/svg"
xmlns="http://www.example.com/"
xmlns:sodipodi="http://www.example.com/sodipodi"
xmlns:inkscape="http://www.example.com/inkscape"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
width="586.25"
height="743.75"
xml:space="preserve"
sodipodi:docname="some_svg_file.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<!-- 部分内容已移除以缩短代码 -->
</svg>
XML;

$svg = new SimpleXMLElement($RawXML);

$height = $svg['height'];
$width = $svg['width'];

echo
"宽度 x 高度为: ${width} x ${height} \n";

?>
daniel dot oconnor at gmail dot com
18年前
SimpleXML 处理命名空间,但此处文档说明得不太好。

如果你想解析,比如说,一个OpenOffice清单文件或一段RDF/XML,你必须通过命名空间URL获取元素和属性。

示例
<?php
function display($in) {
if (
file_exists($in)) {
$xml = simplexml_load_file($in);
} else {
throw new
Exception($in . "文件不存在");
}

$manifest = $xml->children('http://openoffice.org/2001/manifest');

foreach (
$manifest->xpath('//manifest:file-entry') as $file) {
foreach (
$file->attributes('http://openoffice.org/2001/manifest') as $key => $value) {
print
"键值:" . $key . "\n";
print
"值:" . $value . "\n";
}
}

}
?>

文件: manifest.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.writer" manifest:full-path="/"/>
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
<manifest:file-entry manifest:media-type="application/binary" manifest:full-path="layout-cache"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
<manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/thumbnail.png"/>
<manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
</manifest:manifest>
onPHP5.com
17 年前
文档中没有说明,但是如果源XML声明使用其他编码,SimpleXML会将所有文本转换为UTF-8。例如,如果源代码有以下XML声明

<?xml version="1.0" encoding="windows-1251" ?>

则结果SimpleXMLElement中的所有文本将自动采用UTF-8编码。
Arnaud Bienvenu
18年前
从PHP 5.1.4开始,尝试迭代不存在的节点实际上会创建该节点。

<?
$xml = simplexml_load_string('<root></root>');
foreach($xml->b as $dummy);
echo $xml->asXML();
?>

输出结果为

<?xml version="1.0"?>
<root><b/></root>

你可能认为这是一个bug,但PHP开发者似乎将其视为一个特性: http://bugs.php.net/bug.php?id=39164
julien dot breiner at laposte dot net
12年前
仅使用SimpleXML合并两个XML文件

<?php
private function mergeXML(&$base, $add)
{
$new = $base->addChild($add->getName());
foreach (
$add->attributes() as $a => $b) {
$new[$a] = $b;
}
foreach (
$add->children() as $child) {
$this->mergeXML($new, $child);
}
}
?>

使用方法:<?php mergeXML($xmlElement, simplexml_load_string($toMerge)) ?>
nelson_menezes at yahoo dot co dot uk
19 年前
请注意,SimpleXML期望读取和输出UTF-8编码的XML。如果输入XML文件不是UTF-8编码,则需要在文件顶部添加类似这样的行(根据使用的编码进行调整)

<?xml version="1.0" encoding="ISO-8859-1" ?>

在输出方面,如果未使用UTF-8进行服务/处理,则需要使用utf8_decode() [红色。但这只适用于ISO-8859-1,不适用于其他编码]。常见错误: http://bugs.php.net/bug.php?id=28154
k dot antczak at livedata dot pl
13 年前
一个快速代码片段,用于将XML对象转换为数组

<?php
function xml2array ( $xmlObject, $out = array () )
{
foreach ( (array)
$xmlObject as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? xml2array ( $node ) : $node;

return
$out;
}
?>

玩的开心!;-)
james dot ellis at gmail dot com
16 年前
虽然SimpleXML是一个强大的工具,但使用它来处理大型XML文档和字符串的开发者应该仔细考虑其内存使用需求。
SimpleXML需要在对树进行任何处理操作之前,整个XML树都可用——这需要整个树都在内存中。对于40kb的XML文件来说是可以的,但是当处理>100MB的文件时,你会看到性能下降,尤其是在服务器繁忙的情况下。

处理大型XML文件的替代方法是XMLReader类,它以流模式运行,这里有一个很好的教程
http://www.ibm.com/developerworks/library/x-pullparsingphp.html

XML是一种非常冗长的格式。如果你正在处理大型数据结构,尤其是在web服务中,你真的需要将数据表示为XML树吗?——其他序列化格式,如JSON、序列化PHP、Google Protocol Buffers(http://code.google.com/p/protobuf/)甚至CSV,在处理大型文件时,可以显著减少处理时间、带宽和负载。一个110MB的XML文件可以变成一个65MB的CSV文件,其中包含相同的数据,仅仅是因为数据标识符(标签)在整个文档中只表示一次。
m0sh3 at hotmail dot com
16 年前
注意像这样的特性

<?php

$a
= new SimpleXMLElement('<a><b/></a>');

$a->b = 'test &amp; test';
$a->c = 'test &amp; test';

print_r($a);
/*
输出:

SimpleXMLElement Object
(
[b] => test & test
[c] => test &amp; test
)
*/
codje2 at lboro dot ac dot uk
17 年前
有时混合使用数据存储类型是很好的。这是一个非常简单的SQL到XML转换器。向其提供一个SQL查询,它将结果输出为XML。

第一个参数应该是mysql_query的结果
(可选)第二个是每行的xml名称(即XML的第二层深度)
(可选)第三个是XML文档的名称,根名称

<?php
$result
=mysql_query("SELECT * FROM users");
sql_to_xml($result,"users","members");

function
sql_to_xml($mysql_result,$row_name="row",$doc_name="root")
{

$xml= new SimpleXMLElement("<$doc_name></$doc_name>");
while(
$line=mysql_fetch_assoc($mysql_result))
{
$row=$xml->addChild($row_name);
foreach(
$line as $column => $value)
{
$row->$column="$value";
}
}
return
$xml->asXML();
}

?>
[email protected]
17 年前
创建新的XML文档并添加包含变音符号等文本时

<?php $SimpleXMLElement->asXML(); ?>

将静默地不输出任何包含变音符号的内容。

添加变音符号和其它符号时使用htmlentities()来解决“问题”。
[email protected]
17 年前
如果需要对从SimpleXML文档中提取的值进行数学计算,则可能需要将值强制转换为浮点数以防止精度丢失。以下是一个示例

<?php
$objXML
= new SimpleXMLElement('<test x="-123.45"></test>');

// 正确显示
echo $objXML['x']."\n";

// 我们丢失了小数位
echo $objXML['x'] + $objXML['x']."\n";

$x = $objXML['x'];

// 如果我们强制转换金额,则此方法有效
echo (float)$objXML['x'] + (float)$objXML['x']."\n";

// 对字符串进行计算,没问题
echo "-123.45" + "-123.45";

?>

这是因为$objXML['x']既不是字符串(php会自动强制转换),也不是浮点数,而是一个SimpleXMLElement对象。

"echo var_dump($x);" 将输出以下内容
~~
object(SimpleXMLElement)#3 (1) {
[0]=>
string(7) "-123.45"
}
~~

我在php上提交了一个bug请求,但这是他们给我的答复

~~
状态:不会修复

此行为由引擎定义,而不是扩展定义。对对象执行数学运算时,它们将被视为整数。用户有责任将对象强制转换为适当的类型以保持正确的精度。
~~
[email protected]
17 年前
如果处理大量的HTML或混合内容XML,可能需要使用DOM函数而不是SimpleXML。例如
<?php
$html
= new SimpleXMLElement('<div><p>Some text, <a href="#">a link,</a> more text</p></div>');

echo
$html->p->a,"<br>\n"; // "a link,"
echo $html->p; // "Some text, more text" (!)
?>
在上面的示例中,由于SimpleXML表示数据的方式,无法重建原始标记。
[email protected]
17 年前
设置属性时出现内存泄漏(如示例(#示例 2134。设置值))

这在web脚本中可能不会被注意到(除非你做了大量的xml操作),但我在我处理大量XML文件的独立脚本中遇到了这个问题。

以下代码将很快消耗内存

<?php
include 'example.php';

while (
true) {
$xml = new SimpleXMLElement($xmlstr);
$xml->movie[0]->characters->character[0]->name = 'Miss Coder';
}
?>

而这似乎行为正确

<?php
include 'example.php';

while (
true) {
$xml = new SimpleXMLElement($xmlstr);
$c = $xml->xpath("//character");
$c[0]->name = 'Miss Coder';
}
?>

这看起来像是bug #38604,我刚刚确认在6.0.0-dev(至少在Windows上)中已修复。在5.2.1或5.2.2-dev(2/21版本)中没有修复,因此对于5.2用户,请使用第二种形式来避免泄漏。
[email protected]
18年前
使用var_export调试元素属性时要小心——它不起作用!始终使用print()或类似方法来检查元素属性的内容。
Pyetro Costa [[email protected]]
5年前
在查看了"https://php.net/manual/en/ref.simplexml.php#103617"的xml2array函数和"https://php.net/manual/en/ref.simplexml.php # 112038"之后,仍然进行了更改以将空标签转换为null……我觉得需要将结果作为对象来处理,保持数组的数组形式。最终得到了这个函数
<?php

private function xml2Object($xmlObject, $out = null) {
$out = (is_object($xmlObject) ? new \stdClass : array());
foreach ((array)
$xmlObject as $index => $node )
if (
is_array($out)) {
$out[$index] = (is_object($node) || is_array($node)) ? (($node instanceof \SimpleXMLElement) && count((array) $node)==0 ? null : $this->xml2Object($node)) : $node;
} else
$out->{$index} = (is_object($node) || is_array($node)) ? (($node instanceof \SimpleXMLElement) && count((array) $node)==0 ? null : $this->xml2Object($node)) : $node;
return
$out;
}
?>

函数的结果如下所示
<?php
$xml
= simplexml_load_string('<?xml version="1.0" encoding="UTF-8" standalone="no"?><results><l1_elm1><l2_elm1>Some Text</l2_elm1><l2_elm2/></l1_elm1><l1_elm2><l2_elm1><l3_elm1>Array Index[0] - First property</l3_elm1><l3_elm2>Array Index[0] - Second property</l3_elm2><l3_elm3>Array Index[0] - Third property</l3_elm3></l2_elm1><l2_elm1><l3_elm1>Array Index[1] - First property</l3_elm1><l3_elm2>Array Index[1] - Second property</l3_elm2><l3_elm3>Array Index[1] - Third property</l3_elm3></l2_elm1></l1_elm2><l1_elm3/></results>');

var_dump( $this->xml2Object($xml) );

// var_dump xml2Object 结果
object(stdClass)#339 (3) {
["l1_elm1"]=>object(stdClass)#344 (2) {
["l2_elm1"]=>string(9) "Some Text"
["l2_elm2"]=>NULL
}
[
"l1_elm2"]=>object(stdClass)#347 (1) {
["l2_elm1"]=>array(2) {
[
0]=>object(stdClass)#348 (3) {
["l3_elm1"]=>string(31) "Array Index[0] - First property"
["l3_elm2"]=>string(32) "Array Index[0] - Second property"
["l3_elm3"]=>string(31) "Array Index[0] - Third property"
}
[
1]=>object(stdClass)#349 (3) {
["l3_elm1"]=>string(31) "Array Index[1] - First property"
["l3_elm2"]=>string(32) "Array Index[1] - Second property"
["l3_elm3"]=>string(31) "Array Index[1] - Third property"
}
}
}
[
"l1_elm3"]=>NULL
}

// VarDump Symphony xml2Object 结果类似于
object (#345) {
+"l1_elm1": object (#339) {
+"l2_elm1": "Some Text"
+"l2_elm2": null
}
+
"l1_elm2": object (#347) {
+"l2_elm1": array(2) {
[
0] => object (#348) {
+"l3_elm1": "Array Index[0] - First property"
+"l3_elm2": "Array Index[0] - Second property"
+"l3_elm3": "Array Index[0] - Third property"
}
[
1] => object (#349) {
+"l3_elm1": "Array Index[1] - First property"
+"l3_elm2": "Array Index[1] - Second property"
+"l3_elm3": "Array Index[1] - Third property"
}
]
}
+
"l1_elm3": null
}
?>
thomas at guenneguez dot com
12年前
仅使用SimpleXML合并两个XML文件
如果注释只包含值,则函数已修正。

<?php
function mergeXML(&$base, $add)
{
if (
$add->count() != 0 )
$new = $base->addChild($add->getName());
else
$new = $base->addChild($add->getName(), $add);
foreach (
$add->attributes() as $a => $b)
{
$new->addAttribute($a, $b);
}
if (
$add->count() != 0 )
{
foreach (
$add->children() as $child)
{
mergeXML($new, $child);
}
}
}
?>

使用方法:<?php mergeXML($xmlElement, simplexml_load_string($toMerge)) ?>
philippe_marc_--a---t--_novartis_com
16 年前
提示:如果您在使用 SimpleXML 时遇到内存问题。
您可能需要使用 PHP>5.2.5 来避免这种情况: http://bugs.php.net/bug.php?id=38604
如果不可能,请避免类似“foreach ( $xmldata->node as $node )”这样的调用。
php at werner dash ott dot de
17 年前
关于 SimpleXML 和会话

在会话上下文中创建 SimpleXML 对象(准确地说:SimpleXMLElement 对象)并将其存储在 $_SESSION['XMLobject'] 中时,此对象不会“保留”在会话中!

重新进入会话时,print_r($_SESSION['XMLobject']) 显示

['XMLobject'] => SimpleXMLElement Object
警告:节点不再存在于 /your_php_file.php 的 xyz 行
(
)

(为了更好的可读性,消息已简化。)
Jason Sheets <jsheets at shadonet dot com>
18年前
这是我的 Simple XML 到数组函数,它是递归的,并且具有保持键值关系的优点,并且对我很有效。

<?php
function XMLToArray($xml)
{
if (
$xml instanceof SimpleXMLElement) {
$children = $xml->children();
$return = null;
}

foreach (
$children as $element => $value) {
if (
$value instanceof SimpleXMLElement) {
$values = (array)$value->children();

if (
count($values) > 0) {
$return[$element] = XMLToArray($value);
} else {
if (!isset(
$return[$element])) {
$return[$element] = (string)$value;
} else {
if (!
is_array($return[$element])) {
$return[$element] = array($return[$element], (string)$value);
} else {
$return[$element][] = (string)$value;
}
}
}
}
}

if (
is_array($return)) {
return
$return;
} else {
return
$false;
}
}
?>
Pyetro Costa [pyetrosafe at gmail dot com]
5年前
这只是对 https://php.net/manual/en/ref.simplexml.php#112038 函数的一个新的调整。

添加is_array检查至少将转换提高了3个级别,但是空标签被转换为SimpleXMLElement类对象,添加类型和大小检查,将这些空标签转换为null。

参见示例
<?php
// 参考 https://php.net/manual/en/ref.simplexml.php#112038 中的函数
function xml2array($xmlObject, $out = array ()) {
foreach ((array)
$xmlObject as $index => $node )
$out[$index] = (is_object($node) || is_array($node)) ? xml2array($node) : $node;
return
$out;
}

$xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8" standalone="no"?><results><level1><l1_elm1><level2><l2_elm1>Some Text</l2_elm1><l2_elm2/></level2></l1_elm1><l1_elm2>Other String</l1_elm2><l1_elm3/></level1></results>');
$XML2Array = xml2array($xml);
var_dump($xml);
var_dump($XML2Array);

// 结果如下所示
// simplexml_load_string 结果
object(SimpleXMLElement)#227 (1) {
["level1"]=>object(SimpleXMLElement)#226 (3) {
["l1_elm1"]=>object(SimpleXMLElement)#236 (1) {
["level2"]=>object(SimpleXMLElement)#238 (2) {
["l2_elm1"]=>string(9) "Some Text"
["l2_elm2"]=>object(SimpleXMLElement)#239 (0) {}
}
}
[
"l1_elm2"]=>string(12) "Other String"
["l1_elm3"]=>object(SimpleXMLElement)#237 (0) {}
}
}

// xml2array 函数结果
array(1) {
[
"level1"]=>array(3) {
[
"l1_elm1"]=>array(1) {
[
"level2"]=>array(2) {
[
"l2_elm1"]=>string(9) "Some Text"
["l2_elm2"]=>array(0) {}
}
}
[
"l1_elm2"]=>string(12) "Other String"
["l1_elm3"]=>array(0) {}
}
}
?>

现在,检查节点类型和大小,如果节点是 SimpleXMLElement 实例且计数为 0,则将值设置为 null(或者根据您的喜好设置为空字符串 "");
<?php
function xml2array($xmlObject, $out = array ()) {
foreach ((array)
$xmlObject as $index => $node )
$out[$index] = (is_object($node) || is_array($node)) ? (($node instanceof \SimpleXMLElement) && count((array) $node)==0 ? null : xml2array($node)) : $node;
return
$out;
}

$xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8" standalone="no"?><results><level1><l1_elm1><level2><l2_elm1>Some Text</l2_elm1><l2_elm2/></level2></l1_elm1><l1_elm2>Other String</l1_elm2><l1_elm3/></level1></results>');
var_dump(xml2array($xml));

// 现在结果如下所示
array(1) {
[
"level1"]=>array(3) {
[
"l1_elm1"]=>array(1) {
[
"level2"]=>array(2) {
[
"l2_elm1"]=>string(9) "Some Text"
["l2_elm2"]=>NULL
}
}
[
"l1_elm2"]=>string(12) "Other String"
["l1_elm3"]=>NULL
}
}
?>
nathan at gimpstraw dot com
16 年前
我正在使用 SimpleXML 处理从 API 请求返回的数据,我遇到了 CDATA 问题和从 HTML 实体获得的错误,这里是我想出的一个解决方案,不知道它是不是最实用的,但它正在工作。

<?php
$str
= <<< XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<menu>
<item>
<title><![CDATA[Caf&eacute;]]></title>
<description><![CDATA[Some description.]]></description>
</item>
</menu>
XML;

$str = preg_replace("/\<\!\[CDATA\[(.*?)\]\]\>/ies", "'[CDATA]'.base64_encode('$1').'[/CDATA]'", $str);
$xml = new SimpleXMLElement($str);

// 返回 item title
foreach ($xml->item as $item) {
$tmp = (string) $item->title;
$tmp = preg_replace("/\[CDATA\](.*?)\[\/CDATA\]/ies", "base64_decode('$1')", $tmp);
echo
$tmp;
}
?>
Andrez zenarter at hotmail dot com
15年前
我只是想补充一点:
"将一个 SimpleXML 追加/组合/合并到另一个 SimpleXML"
父元素也应该有属性。

<?php

function append_simplexml(&$simplexml_to, &$simplexml_from)
{

static
$firstLoop=true;

// 在这里向父元素添加属性
if( $firstLoop )
{
foreach(
$simplexml_from->attributes() as $attr_key => $attr_value )
{
$simplexml_to->addAttribute($attr_key, $attr_value);
}
}

foreach (
$simplexml_from->children() as $simplexml_child)
{
$simplexml_temp = $simplexml_to->addChild($simplexml_child->getName(), (string) $simplexml_child);
foreach (
$simplexml_child->attributes() as $attr_key => $attr_value)
{
$simplexml_temp->addAttribute($attr_key, $attr_value);
}

$firstLoop=false;

append_simplexml($simplexml_temp, $simplexml_child);
}

unset(
$firstLoop=false );
}

?>

我有一个问题,就是将一个对象赋值给一个变量,稍后这个变量用作对象,然后我找到了上面的代码,它解决了我的部分问题。它应该也包含父元素名称的赋值,但却没有。有什么更好的代码吗?
codejunky32 at NOSPAM dot com
15年前
只想补充一篇关于如何从 SimpleXMLElement 中提取值的帖子。它不像你想象的那么简单。因为它是一个复杂的对象,你不能直接访问元素。这是一个代表 SimpleXmlElement 的 var_dump 数据样本

array(1) {
[0]=>
object(SimpleXMLElement)#13 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(5) "title"
}
[0]=>
string(19) "PHP Tech Book"
}
}

如果您想提取书的标题,您必须将指定的元素强制转换为字符串,如下所示。
$newTitle = (string) $title[0];

$title 变量是从 xml 文档中使用例如 simplexml_load_string 提取的 SimpleXMLElement。要最初从 xml 文档访问标题元素,您可以使用 xpath 这样做。
$title = $doc->xpath('str[@name="title"]');

希望这对某些人有所帮助。
info at ajaxforum dot ru
15年前
追加/组合/合并一个 simplexml 到另一个

<?php
include 'example.php';
$el1 = new SimpleXMLElement($xmlstr);
$el2 = new SimpleXMLElement($xmlstr);

// 错误的方法!
// php 将 $el2->movie[0] 静默转换为字符串
$el1->addChild('movie', $el2->movie[0]);

// 错误的方法!
// php 5.1 将 $el2->movie[0] 转换为字符串并生成警告:尚无法将复杂类型赋值给属性。无法将复杂类型赋值给节点
// php 5.2 将 $el2->movie[0] 静默转换为字符串
$el1->addChild('movie');
$el1->movie[2] = $el2->movie[0];

// 正确的方法!
$el1_movie = $el1->addChild('movie');
append_simplexml($el1_movie, $el2->movie[0]);

echo
"<pre>"; print_r($el1); echo "</pre>";

/**
* 将一个 simplexml 添加到另一个
*
* @param object $simplexml_to
* @param object $simplexml_from
* @author Boris Korobkov
* @link http://www.ajaxforum.ru/
*/
function append_simplexml(&$simplexml_to, &$simplexml_from)
{
foreach (
$simplexml_from->children() as $simplexml_child)
{
$simplexml_temp = $simplexml_to->addChild($simplexml_child->getName(), (string) $simplexml_child);
foreach (
$simplexml_child->attributes() as $attr_key => $attr_value)
{
$simplexml_temp->addAttribute($attr_key, $attr_value);
}

append_simplexml($simplexml_temp, $simplexml_child);
}
}
?>
To Top