PHP Conference Japan 2024

simplexml_load_string

(PHP 5, PHP 7, PHP 8)

simplexml_load_string 将XML字符串解释为对象

描述

simplexml_load_string(
    string $data,
    ?string $class_name = SimpleXMLElement::class,
    int $options = 0,
    string $namespace_or_prefix = "",
    bool $is_prefix = false
): SimpleXMLElement|false

接受一个格式良好的XML字符串并将其作为对象返回。

参数

data

格式良好的XML字符串

class_name

您可以使用此可选参数,以便simplexml_load_string() 将返回指定类的对象。该类应扩展SimpleXMLElement 类。

options

按位 OR libxml 选项常量

namespace_or_prefix

命名空间前缀或URI。

is_prefix

如果namespace_or_prefix 是前缀,则为true,如果是URI,则为false;默认为false

返回值

返回一个objectSimpleXMLElement,其属性包含XML文档中保存的数据,或者在失败时返回false

警告

此函数可能返回布尔值false,但也可能返回计算结果为false的非布尔值。请阅读有关布尔值 的部分以了解更多信息。使用=== 运算符 来测试此函数的返回值。

错误/异常

为在XML数据中找到的每个错误生成E_WARNING 错误消息。

提示

使用libxml_use_internal_errors() 来抑制所有XML错误,并使用libxml_get_errors() 来迭代这些错误。

示例

示例 #1 解读XML字符串

<?php
$string
= <<<XML
<?xml version='1.0'?>
<document>
<title>Forty What?</title>
<from>Joe</from>
<to>Jane</to>
<body>
I know that's the answer -- but what's the question?
</body>
</document>
XML;

$xml = simplexml_load_string($string);

print_r($xml);
?>

以上示例将输出

SimpleXMLElement Object
(
  [title] => Forty What?
  [from] => Joe
  [to] => Jane
  [body] =>
   I know that's the answer -- but what's the question?
)

此时,您可以使用$xml->body 等。

参见

添加笔记

用户贡献笔记 22 条笔记

ascammon at hotmail dot com
13 年前
我很难找到这个文档,所以在这里发布它,以防万一它能帮助到其他人

如果您想使用多个libxml选项,请用管道分隔它们,如下所示

<?php
$xml
= simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
?>
Diego Araos, diego at klapmedia dot com
13 年前
一种更简单的将结果转换为数组的方法(需要json模块)。

<?php
function object2array($object) { return @json_decode(@json_encode($object),1); }
?>

示例
<?php
$xml_object
=simplexml_load_string('<SOME XML DATA');
$xml_array=object2array($xml_object);
?>
meustrus
9 年前
小心检查解析错误。空SimpleXMLElement可能解析为FALSE,如果您的XML不包含文本或仅包含命名空间元素,则您的错误检查可能错误。检查解析错误时,始终使用`=== FALSE`。

<?php

$xml
= <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Root xmlns:ns1="http://example.com/custom">
<ns1:Node>There's stuff here</ns1:Node>
</ns1:Root>
XML;

$simplexml = simplexml_load_string($xml);

// 这将输出 "Parse Error"。
echo ($simplexml ? 'Valid XML' : 'Parse Error'), PHP_EOL;

// 但这将输出 "There's stuff here",证明 SimpleXML 对象已成功创建。
echo $simplexml->children('http://example.com/custom')->Node, PHP_EOL;

// 请改用以下方法:
echo ($simplexml !== FALSE ? 'Valid XML' : 'Parse Error'), PHP_EOL;

?>

参见

https://bugs.php.net/bug.php?id=31045
https://bugs.php.net/bug.php?id=30972
https://bugs.php.net/bug.php?id=69596
rowan dot collins at gmail dot com
16年前
似乎有很多关于 SimpleXML 处理 CDATA 数据存在“问题”的讨论,以及编写函数来去除 CDATA 数据等等。起初我也这么认为,但在 PHP 5.2.6 版本下,它的行为实际上是正常的。

关键在于上面例子 #6 中提到的内容
http://uk2.php.net/manual/en/simplexml.examples.php

“要将元素或属性与字符串进行比较,或将其传递给需要字符串的函数,必须使用 (string) 将其强制转换为字符串。否则,PHP 会将元素视为对象。”

如果标签包含 CDATA 数据,SimpleXML 会记住这一事实,将其与元素的字符串内容分开表示。因此,某些函数(包括 print_r())可能不会显示您预期的结果。但是,如果您显式地强制转换为字符串,则会得到所有内容。

<?php
$xml
= simplexml_load_string('<foo>Text1 &amp; XML entities</foo>');
print_r($xml);
/*
SimpleXMLElement Object
(
[0] => Text1 & XML entities
)
*/

$xml2 = simplexml_load_string('<foo><![CDATA[Text2 & raw data]]></foo>');
print_r($xml2);
/*
SimpleXMLElement Object
(
)
*/
// 我的 CDATA 数据去哪里了?

// 让我们尝试显式转换
print_r( (string)$xml );
print_r( (string)$xml2 );
/*
Text1 & XML entities
Text2 & raw data
*/
// 好多了
?>
bojan
16年前
如前所述,不要使用 var_dump() 或 print_r() 来查看 SimpleXML 对象结构,因为它们并不总是返回您期望的结果。
考虑以下情况

<?php

// xml 数据
$xml_txt = '
<root>
<folder ID="65" active="1" permission="1"><![CDATA[aaaa]]></folder>
<folder ID="65" active="1" permission="1"><![CDATA[bbbb]]></folder>
</root>'
;

// 将 xml 加载到 SimpleXML 对象中
$xml = simplexml_load_string($xml_txt, 'SimpleXMLElement', LIBXML_NOCDATA);//LIBXML_NOCDATA LIBXML_NOWARNING

// 查看对象结构
print_r($xml);

/* 这将输出
SimpleXMLElement Object
(
[folder] => Array
(
[0] => aaaa
[1] => bbbb
)

)
*/

// 但是...
foreach ($xml->folder as $value){
print_r($value);
}
/* 输出每个 folder 元素的完整结构:
SimpleXMLElement Object
(
[@attributes] => Array
(
[ID] => 65
[active] => 1
[permission] => 1
)

[0] => aaaa
)

SimpleXMLElement Object
(
[@attributes] => Array
(
[ID] => 65
[active] => 1
[permission] => 1
)

[0] => bbbb
)

*/
?>
amir_abiri at ipcmedia dot com
16年前
这似乎没有在任何地方记录,但是您可以参考元素“值”来更改它,如下所示:

<?php
$xml
= simplexml_load_string('<root><number>1</number></root>');
echo
$xml->asXml(). "\n\n";

$xml->number->{0} = $xml->number->{0} + 1;

echo
$xml->asXml();
?>

输出
<?xml version="1.0"?>
<root><number>1</number></root>

<?xml version="1.0"?>
<root><number>2</number></root>

但是,这只适用于直接赋值,不适用于任何其他运算符。

<?php
$xml
= simplexml_load_string('<root><number>1</number></root>');
echo
$xml->asXml(). "\n\n";

$xml->number->{0} += 1;
// 或:
$xml->number->{0}++;

echo
$xml->asXml();
?>

以上两种情况都会导致以下输出:

<?xml version="1.0"?>
<root><number>1</number></root>

<?xml version="1.0"?>
<root><number>1<0/></number></root>
nbijnens at servs dot eu
17年前
请注意,并非所有 LIBXML 选项都支持 options 参数。

例如,LIBXML_XINCLUDE 不起作用。但是,有一个解决方法

<?php
$xml
= new DOMDocument();
$xml->loadXML ($XMLString);

$xml->xinclude();
$xml = simplexml_import_dom($xml);

?>
hattori at hanso dot com
17年前
当序列化包含 html CDATA 的字段时,以下解决方法存在问题。对于 HTML 以外的任何其他内容类型,请尝试修改函数 parseCDATA。
只需在序列化之前添加以下几行代码。
这也是针对此错误的解决方法 http://bugs.php.net/bug.php?id=42001

<?PHP
if(strpos($content, '<![CDATA[')) {
function
parseCDATA($data) {
return
htmlentities($data[1]);
}
$content = preg_replace_callback(
'#<!\[CDATA\[(.*)\]\]>#',
'parseCDATA',
str_replace("\n", " ", $content)
);
}
?>
mindpower
17年前
一个简单的扩展,添加了一个用于检索特定属性的方法。

<?php
class simple_xml_extended extends SimpleXMLElement
{
public function
Attribute($name)
{
foreach(
$this->Attributes() as $key=>$val)
{
if(
$key == $name)
return (string)
$val;
}
}

}

$xml = simplexml_load_string('
<xml>
<dog type="poodle" owner="Mrs Smith">Rover</dog>
</xml>'
, 'simple_xml_extended');

echo
$xml->dog->Attribute('type');

?>

输出 'poodle'

我更喜欢使用这种技术而不是类型转换属性。
javalc6 at gmail dot com
16年前
我想将一个包含字符串和其他相同类型数组的数组转换为一个 SimpleXML 对象。

这是我开发的用于执行此转换的函数 array2xml 的代码。请注意,这段代码很简单,没有任何检查。

<?php
function array2xml($array, $tag) {

function
ia2xml($array) {
$xml="";
foreach (
$array as $key=>$value) {
if (
is_array($value)) {
$xml.="<$key>".ia2xml($value)."</$key>";
} else {
$xml.="<$key>".$value."</$key>";
}
}
return
$xml;
}

return
simplexml_load_string("<$tag>".ia2xml($array)."</$tag>");
}

$test['type']='lunch';
$test['time']='12:30';
$test['menu']=array('entree'=>'salad', 'maincourse'=>'steak');

echo
array2xml($test,"meal")->asXML();
?>
Bob
15年前
这是一个简单的SimpleXML封装函数。
据我所知,它与Julio Cesar Oliveira(上面)的函数功能相同。
它将XML字符串解析成一个多维关联数组。
第二个参数是一个回调函数,该函数会对所有数据执行操作(例如,如果您希望所有数据都被修剪,就像Julio在他的函数中所做的那样,只需将'trim'作为第二个参数传递)。
<?php
function unserialize_xml($input, $callback = null, $recurse = false)
/* bool/array unserialize_xml ( string $input [ , callback $callback ] )
* 反序列化XML字符串,返回一个多维关联数组,可以选择对所有非数组数据运行回调函数
* 所有失败都返回false
* 注意:
* 根XML标签将被剥离
* 由于其递归特性,unserialize_xml() 也支持 SimpleXMLElement 对象和数组作为输入
* 使用 simplexml_load_string() 进行 XML 解析,有关更多信息,请参阅 SimpleXML 文档
*/
{
// 获取输入,如果它是递归的顶层,则使用 simplexml 加载 xml 字符串
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input): $input;
// 将 SimpleXMLElements 转换为数组
if ($data instanceof SimpleXMLElement) $data = (array) $data;
// 递归进入数组
if (is_array($data)) foreach ($data as &$item) $item = unserialize_xml($item, $callback, true);
// 运行回调函数并返回
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
?>
AllenJB
12年前
<?php
$xml
= json_decode(json_encode((array) simplexml_load_string($string)), 1);
?>

提醒一下,`json_encode` 会尝试将数据转换为 UTF-8,而无需特定了解源编码。如果您没有使用 UTF-8,则此方法可能会导致编码问题。
Julio Cesar Oliveira
15年前
XML2Array 函数现在是递归的!

<?php
function XML2Array ( $xml , $recursive = false )
{
if ( !
$recursive )
{
$array = simplexml_load_string ( $xml ) ;
}
else
{
$array = $xml ;
}

$newArray = array () ;
$array = ( array ) $array ;
foreach (
$array as $key => $value )
{
$value = ( array ) $value ;
if ( isset (
$value [ 0 ] ) )
{
$newArray [ $key ] = trim ( $value [ 0 ] ) ;
}
else
{
$newArray [ $key ] = XML2Array ( $value , true ) ;
}
}
return
$newArray ;
}
?>
artistan at gmail dot com
9 年前
这是我对Bob的简单SimpleXML封装函数的更新。
我注意到他的版本会将一个空的SimpleXMLElement转换成一个空数组。

<?php
/**
* https://php.net/manual/en/function.simplexml-load-string.php#91564
*
* bool/array unserialize_xml ( string $input [ , callback $callback ] )
* 反序列化XML字符串,返回一个多维关联数组,可以选择对所有非数组数据运行回调函数
* 所有失败都返回false
* 注意:
* 根XML标签将被剥离
* 由于其递归特性,unserialize_xml() 也支持 SimpleXMLElement 对象和数组作为输入
* 使用 simplexml_load_string() 进行 XML 解析,有关更多信息,请参阅 SimpleXML 文档
*
* @param $input
* @param null $callback
* @param bool $recurse
* @return array|mixed
*
*/
function unserialize_xml($input, $callback = null, $recurse = false)
{
// 获取输入,如果它是递归的顶层,则使用 simplexml 加载 xml 字符串
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input): $input;
// 将 SimpleXMLElements 转换为数组
if ($data instanceof SimpleXMLElement){
if(!empty(
$data)){
$data = (array) $data;
} else {
$data = '';
}
}
// 递归进入数组
if (is_array($data)) foreach ($data as &$item) $item = unserialize_xml($item, $callback, true);
// 运行回调函数并返回
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
?>
匿名用户
12年前
使用 `libxml_disable_entity_loader()` 来限制加载外部文件。参见 http://www.idontplaydarts.com/2011/02/scanning-the-internal-network-using-simplexml/
jeff at creabilis dot com
15年前
如果您想设置输出xml的字符集,只需设置encoding属性,如下所示:

<?php simplexml_load_string('<?xml version="1.0" encoding="utf-8"?><xml/>'); ?>

由 `$xml->asXML` 生成的 XML 输出将包含带重音符号的字符,例如“é”,而不是“é”。

希望这有帮助
[email protected]
17年前
警告

解析 XML 数据时,遇到字符 0 将停止。
请避免在 XML 数据中使用此字符。
[email protected]
20年前
SimpleXML 无法在 foreach 循环中简单地处理 CDATA 节。

<?php
$sx
= simplexml_load_string('
<test>
<one>hi</one>
<two><![CDATA[stuff]]></two>
<t>
<for>two</for>
</t>
<multi>one</multi>
<multi>two</multi>
</test>'
);
foreach((array)
$sx as $tagname => $val) {
if (
is_string($val)) {
// <one> 将在此处
} elseif (is_array($val)) {
// <multi> 将在此处,因为它出现多次
} elseif (is_object($val)) {
// <t> 将在此处,因为它包含标签
// <two> 将在此处,因为它包含 CDATA!
}
}
?>

要在循环中进行测试,请执行以下操作

<?php
if (count((array) $val) == 0) {
// 这不是包含其他标签的标签
$val = '' . $val;
// 现在 CDATA 以神奇的方式显示了。
}
?>
Pedro
17年前
注意

simplexml_load_string 对于除 (<,>,&," 和 ') 之外的实体存在问题。

请改用数字字符引用!
Maciek Ruckgaber <[email protected]>
19年前
在四处摸索了一段时间后,我突然意识到了一些事情(也许很明显,对我来说却不是)。希望可以帮助其他人避免像我一样浪费时间 :-P

当你遇到类似这样的情况时

<?php
$xmlstr
= <<<XML
<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://foosite.foo/">2328</double>
XML;
?>

SimpleXML 对象将被“转换”为 text() 内容

<?php
$xml
= simplexml_load_string($xmlstr);
echo
$xml; // 这将输出 2328(字符串)
?>
[email protected]
7年前
如果要使用名称空间中存在的类,请使用其全名。simple_load_string 无法识别简短名称。

class.new.php
<?php
namespace foo\bar;

class new extends
SimpleXMLElement
{
public function do()
{
echo
"done";
}
}
?>

false.php
<?php
use \foo\bar\new;

$result = simplexml_load_string($xml, 'new'); // 它会给出警告
$result->do(); // 致命错误
?>

true.php
<?php
use \foo\bar\new;
$result = simplexml_load_string($xml, '\foo\bar\new');

$result->do(); // 输出 done
?>
To Top