我很难找到这个文档,所以在这里发布它,以防它对某人有所帮助
如果您想使用多个 libxml 选项,请使用管道将它们分隔开,如下所示
<?php
$xml = simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
?>
(PHP 5, PHP 7, PHP 8)
simplexml_load_string — 将 XML 字符串解析为对象
$data
,$class_name
= SimpleXMLElement::class,$options
= 0,$namespace_or_prefix
= "",$is_prefix
= false
接受一个格式良好的 XML 字符串并将其返回为一个对象。
data
一个格式良好的 XML 字符串
class_name
您可以使用此可选参数,以便 simplexml_load_string() 返回指定类的对象。该类应扩展 SimpleXMLElement 类。
options
按位 OR
的 libxml 选项常量。
namespace_or_prefix
命名空间前缀或 URI。
is_prefix
true
如果 namespace_or_prefix
是一个前缀,false
如果它是一个 URI;默认为 false
。
返回一个 object 类的对象 SimpleXMLElement,其属性包含 xml 文档中保存的数据,或者在失败时返回 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
等。
我很难找到这个文档,所以在这里发布它,以防它对某人有所帮助
如果您想使用多个 libxml 选项,请使用管道将它们分隔开,如下所示
<?php
$xml = simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
?>
将结果转换为数组的更简单方法(需要 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);
?>
注意检查解析错误。空 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
似乎有很多关于 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 & 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
*/
// 好多了
?>
如前所述,不要使用 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
)
*/
?>
虽然没有在任何地方记录,但你可以引用元素的“值”来更改它,如下所示
<?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>
请注意,并非所有 LIBXML 选项都支持 options 参数。
例如,LIBXML_XINCLUDE 不起作用。但是,有一个解决方法
<?php
$xml = new DOMDocument();
$xml->loadXML ($XMLString);
$xml->xinclude();
$xml = simplexml_import_dom($xml);
?>
当序列化包含 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)
);
}
?>
一个简单的扩展,它添加了一个用于检索特定属性的方法
<?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'
我更喜欢使用这种技术,而不是将属性类型转换为字符串。
我想将一个包含字符串和其他相同类型数组的数组转换为 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();
?>
这是我的 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;
}
?>
<?php
$xml = json_decode(json_encode((array) simplexml_load_string($string)), 1);
?>
提醒一下,json_encode 尝试将数据转换为 UTF-8,但没有特定地了解源编码。如果你没有使用 UTF-8,这种方法会导致编码问题。
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 ;
}
?>
这是我对 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;
}
?>
使用 libxml_disable_entity_loader() 来限制外部文件的加载。请参阅 http://www.idontplaydarts.com/2011/02/scanning-the-internal-network-using-simplexml/
如果你想设置输出 XML 的字符集,只需像这样设置 encoding 属性
<?php simplexml_load_string('<?xml version="1.0" encoding="utf-8"?><xml/>'); ?>
由 $xml->asXML 输出的生成的 XML 将包含重音字符,例如 "é" 而不是 "é"。
希望这有帮助
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 以神奇的方式显示出来。
}
?>
用于简单 SAX 读取大型 XML 的包装类 XMLReader
https://github.com/dkrnl/SimpleXMLReader
使用方法示例:http://github.com/dkrnl/SimpleXMLReader/blob/master/examples/example1.php
在四处寻找一段时间后,我突然意识到了一些东西(可能很明显,对我来说不太明显)。希望这能帮助其他人避免浪费时间,就像我一样 :-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(字符串)
?>
如果你想使用一个存在于命名空间中的类,请使用它的全名。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
?>