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

按位 ORlibxml 选项常量

namespace_or_prefix

命名空间前缀或 URI。

is_prefix

true 如果 namespace_or_prefix 是一个前缀,false 如果它是一个 URI;默认为 false

返回值

返回一个 object 类的对象 SimpleXMLElement,其属性包含 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 个注释

35
ascammon at hotmail dot com
13 年前
我很难找到这个文档,所以在这里发布它,以防它对某人有所帮助

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

<?php
$xml
= simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
?>
22
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);
?>
6
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);

// 这将打印 "解析错误"。
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
14
rowan dot collins at gmail dot com
16 年前
似乎有很多关于 SimpleXML 在处理 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
*/
// 好多了
?>
11
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);
}
/* 打印每个文件夹元素的完整结构:
SimpleXMLElement Object
(
[@attributes] => Array
(
[ID] => 65
[active] => 1
[permission] => 1
)

[0] => aaaa
)

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

[0] => bbbb
)

*/
?>
2
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>
3
nbijnens at servs dot eu
16 年前
请注意,并非所有 LIBXML 选项都支持 options 参数。

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

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

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

?>
1
hattori at hanso dot com
16 年前
当序列化包含 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)
);
}
?>
2
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'

我更喜欢使用这种技术,而不是将属性类型转换为字符串。
1
javalc6 at gmail dot com
15 年前
我想将一个包含字符串和其他相同类型数组的数组转换为 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();
?>
1
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;
}
?>
1
AllenJB
11 年前
<?php
$xml
= json_decode(json_encode((array) simplexml_load_string($string)), 1);
?>

提醒一下,json_encode 尝试将数据转换为 UTF-8,但没有特定地了解源编码。如果你没有使用 UTF-8,这种方法会导致编码问题。
1
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 ;
}
?>
0
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;
}
?>
0
Anonymous
12 年前
使用 libxml_disable_entity_loader() 来限制外部文件的加载。请参阅 http://www.idontplaydarts.com/2011/02/scanning-the-internal-network-using-simplexml/
0
jeff at creabilis dot com
14 年前
如果你想设置输出 XML 的字符集,只需像这样设置 encoding 属性

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

由 $xml->asXML 输出的生成的 XML 将包含重音字符,例如 "é" 而不是 "&#xE9;"。

希望这有帮助
0
m dot ament at mailcity dot com
17 年前
警告

解析 XML 数据时,遇到字符 0 就会停止。
请避免在你的 XML 数据中使用这个字符。
0
cellog at php dot net
19 年前
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 以神奇的方式显示出来。
}
?>
-1
Pedro
17 年前
注意

simplexml_load_string 对除 (&lt;, &gt;, &amp;, &quot; 和 &apos;) 之外的实体存在问题。

使用数字字符引用代替!
-2
Maciek Ruckgaber <maciekrb at gmai dot com>
19 年前
在四处寻找一段时间后,我突然意识到了一些东西(可能很明显,对我来说不太明显)。希望这能帮助其他人避免浪费时间,就像我一样 :-P

当你有类似这样的东西时

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

你将拥有被“转换”为 text() 内容的 SimpleXML 对象

<?php
$xml
= simplexml_load_string($xmlstr);
echo
$xml; // 这将输出 2328(字符串)
?>
-4
erguven dot m at gmail dot com
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