基本 SimpleXML 使用

此参考中的许多示例都需要一个 XML 字符串。为了避免在每个示例中重复此字符串,我们将其放入一个文件中,并在每个示例中包含该文件。包含的文件在以下示例部分中显示。或者,您可以创建一个 XML 文档并使用 simplexml_load_file() 阅读它。

示例 #1 包含带有 XML 字符串的文件 example.php

<?php
$xmlstr
= <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>PHP:解析器背后的故事</title>
<characters>
<character>
<name>Ms. Coder</name>
<actor>Onlivia Actora</actor>
</character>
<character>
<name>Mr. Coder</name>
<actor>El Act&#211;r</actor>
</character>
</characters>
<plot>
所以,这种语言。它就像,一种编程语言。或者它是一种
脚本语言?所有的一切都在这部惊悚的恐怖恶搞
纪录片中揭示。
</plot>
<great-lines>
<line>PHP 解决了我所有网页问题</line>
</great-lines>
<rating type="thumbs">7</rating>
<rating type="stars">5</rating>
</movie>
</movies>
XML;
?>

当从一个基本的 XML 文档中提取一个字符串或数字时,SimpleXML 的简易性最为明显。

示例 #2 获取 <plot>

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

echo
$movies->movie[0]->plot;
?>

上面的示例将输出

   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.

访问 XML 文档中包含 PHP 命名约定(例如连字符)不允许的字符的元素,可以通过将元素名称用大括号和撇号括起来来实现。

示例 #3 获取 <line>

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

echo
$movies->{'great-lines'}->line;
?>

上面的示例将输出

PHP solves all my web problems

示例 #4 在 SimpleXML 中访问非唯一元素

当一个元素的多个实例作为单个父元素的子元素存在时,会应用正常的迭代技术。

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

/* 对于每个 <character> 节点,我们都输出一个单独的 <name>。 */
foreach ($movies->movie->characters->character as $character) {
echo
$character->name, ' played by ', $character->actor, PHP_EOL;
}

?>

上面的示例将输出

Ms. Coder played by Onlivia Actora
Mr. Coder played by El ActÓr

注意:

属性($movies->movie 在前面的示例中)不是数组。它们是 可迭代的可访问的 对象。

示例 #5 使用属性

到目前为止,我们只介绍了读取元素名称及其值的工作原理。SimpleXML 还可以访问元素属性。访问元素的属性就像访问 数组 的元素一样。

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

/* 访问第一部电影的 <rating> 节点。
* 输出评分量表,也是。 */
foreach ($movies->movie[0]->rating as $rating) {
switch((string)
$rating['type']) { // 获取属性作为元素索引
case 'thumbs':
echo
$rating, ' thumbs up';
break;
case
'stars':
echo
$rating, ' stars';
break;
}
}
?>

上面的示例将输出

7 thumbs up5 stars

示例 #6 将元素和属性与文本进行比较

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

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

if ((string)
$movies->movie->title == 'PHP:解析器背后的故事') {
print
'我最喜欢的电影。';
}

echo
htmlentities((string) $movies->movie->title);
?>

上面的示例将输出

My favorite movie.PHP: Behind the Parser

示例 #7 比较两个元素

两个 SimpleXMLElements 被认为是不同的,即使它们指向同一个元素。

<?php
include 'example.php';

$movies1 = new SimpleXMLElement($xmlstr);
$movies2 = new SimpleXMLElement($xmlstr);
var_dump($movies1 == $movies2);
?>

上面的示例将输出

bool(false)

示例 #8 使用 XPath

SimpleXML 包含内置的 XPath 支持。要查找所有 <character> 元素

<?php
include 'example.php';

$movies = new SimpleXMLElement($xmlstr);

foreach (
$movies->xpath('//character') as $character) {
echo
$character->name, ' played by ', $character->actor, PHP_EOL;
}
?>

'//' 充当通配符。要指定绝对路径,请省略其中一个斜杠。

上面的示例将输出

Ms. Coder played by Onlivia Actora
Mr. Coder played by El ActÓr

示例 #9 设置值

SimpleXML 中的数据不一定是固定的。该对象允许操作其所有元素。

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

$movies->movie[0]->characters->character[0]->name = 'Miss Coder';

echo
$movies->asXML();
?>

上面的示例将输出

<?xml version="1.0" standalone="yes"?>
<movies>
 <movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Miss Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El Act&#xD3;r</actor>
   </character>
  </characters>
  <plot>
   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <great-lines>
   <line>PHP solves all my web problems</line>
  </great-lines>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>

示例 #10 添加元素和属性

SimpleXML 能够轻松地添加子元素和属性。

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

$character = $movies->movie[0]->characters->addChild('character');
$character->addChild('name', 'Mr. Parser');
$character->addChild('actor', 'John Doe');

$rating = $movies->movie[0]->addChild('rating', 'PG');
$rating->addAttribute('type', 'mpaa');

echo
$movies->asXML();
?>

上面的示例将输出

<?xml version="1.0" standalone="yes"?>
<movies>
 <movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Ms. Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El Act&#xD3;r</actor>
   </character>
  <character><name>Mr. Parser</name><actor>John Doe</actor></character></characters>
  <plot>
   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <great-lines>
   <line>PHP solves all my web problems</line>
  </great-lines>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 <rating type="mpaa">PG</rating></movie>
</movies>

示例 #11 DOM 互操作性

PHP 提供了一种机制可以将 XML 节点在 SimpleXML 和 DOM 格式之间进行转换。本示例演示了如何将 DOM 元素更改为 SimpleXML。

<?php
$dom
= new DOMDocument;
$dom->loadXML('<books><book><title>blah</title></book></books>');
if (!
$dom) {
echo
'Error while parsing the document';
exit;
}

$books = simplexml_import_dom($dom);

echo
$books->book[0]->title;
?>

上面的示例将输出

blah

添加注释

用户贡献注释 10 个注释

rowan dot collins at gmail dot com
9 年前
有一个常用的“技巧”,通常建议将 SimpleXML 对象转换为数组,方法是将其通过 json_encode() 运行,然后通过 json_decode() 运行。我想解释一下为什么这是一个坏主意。

最简单地说,因为 SimpleXML 的全部意义在于比普通数组更容易使用且功能更强大。例如,您可以编写 <?php $foo->bar->baz['bing'] ?>,它的含义与 <?php $foo->bar[0]->baz[0]['bing'] ?> 相同,无论 XML 中有多少个 bar 或 baz 元素;如果您编写 <?php (string)$foo->bar[0]->baz[0] ?>,您将获得该节点的所有字符串内容 - 包括 CDATA 部分 - 无论它是否也有子元素或属性。您还可以访问命名空间信息,能够对 XML 进行简单的编辑,甚至能够“导入”到 DOM 对象中,以便进行更强大的操作。所有这些功能都会在您将对象转换为数组而不是阅读和理解本页上的示例时丢失。

此外,由于它不是为此目的而设计的,因此转换为 JSON 并返回实际上会在某些情况下丢失信息。例如,命名空间中的任何元素或属性都将被简单地丢弃,如果元素也有子元素或属性,则任何文本内容都将被丢弃。有时,这无关紧要,但是如果您养成将所有内容都转换为数组的习惯,那么最终您会为此付出代价。

当然,您可以编写一个更智能的转换,它没有这些限制,但在这一点上,您根本无法从 SimpleXML 中获得任何价值,并且应该只使用更低级别的 XML 解析器函数或 XMLReader 类来创建您的结构。您仍然不会拥有 SimpleXML 的额外便利功能,但这是您的损失。
jishcem at gmail dot com
11 年前
对我来说,使用数组比使用对象更容易,

因此,我使用了这段代码,

$xml = simplexml_load_file('xml_file.xml');

$json_string = json_encode($xml);

$result_array = json_decode($json_string, TRUE);

希望它能帮到某人
匿名
6 年前
如果您的 XML 字符串包含使用“0”和“1”编码的布尔值,那么在将元素直接强制转换为布尔值时,您将遇到问题

$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<values>
<truevalue>1</truevalue>
<falsevalue>0</falsevalue>
</values>
XML;
$values = new SimpleXMLElement($xmlstr);
$truevalue = (bool)$values->truevalue; // true
$falsevalue = (bool)$values->falsevalue; // 也为 true!!!

相反,您需要先强制转换为字符串或整数

$truevalue = (bool)(int)$values->truevalue; // true
$falsevalue = (bool)(int)$values->falsevalue; // false
约瑟夫
2 年前
如何找出节点是否存在

<?xml version='1.0' standalone='yes'?>
<book>
<author>约瑟夫</author>
<isbn></isbn>
</book>

empty($xml->isbn) 将为 true
isset($xml->isbn) 将为 true

empty($xml->title) 将为 true
isset($xml->title) 将为 false
ie dot raymond at gmail dot com
14 年前
如果您需要在响应中输出有效的 xml,请不要忘记将您的标头内容类型设置为 xml,此外还要回显 asXML() 的结果

<?php

$xml
=simplexml_load_file('...');
...
...
xml 内容
...

// 在您的响应中输出 xml:
header('Content-Type: text/xml');
echo
$xml->asXML();
?>
gkokmdam at zonnet dot nl
13 年前
关于 xpath 查询和默认命名空间的快速提示。看起来 SimpleXML 背后的 XML 系统与我认为 .NET 使用的 XML 系统具有相同的运行方式:当需要在默认命名空间中寻址某项内容时,需要使用 registerXPathNamespace 声明命名空间,然后使用其前缀来寻址否则在默认命名空间中存在的元素。

<?php
$string
= <<<XML
<?xml version='1.0'?>
<document xmlns="http://www.w3.org/2005/Atom">
<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);
$xml->registerXPathNamespace("def", "http://www.w3.org/2005/Atom");

$nodes = $xml->xpath("//def:document/def:title");

?>
kdos
13 年前
使用诸如:is_object($xml->module->admin) 来检查是否存在名为“admin”的节点,似乎无法按预期工作,因为 SimpleXML 始终返回一个对象 - 在这种情况下是一个空对象 - 即使特定节点不存在。
对我来说,在这些情况下,传统的 empty() 函数似乎工作得很好。

干杯
Max K.
14 年前
来自 README 文件

SimpleXML 旨在成为一种访问 XML 数据的简便方法。

SimpleXML 对象遵循四个基本规则

1) 属性表示元素迭代器
2) 数字索引表示元素
3) 非数字索引表示属性
4) 字符串转换允许访问文本数据

当迭代属性时,扩展始终迭代
所有具有该元素名称的节点。因此,必须调用 children() 方法
以迭代子节点。但这样做也是如此
foreach ($obj->node_name as $elem) {
// 对 $elem 做些事情
}
始终会导致迭代“node_name”元素。因此,不需要进一步
检查以区分该类型节点的数量。

当通过属性访问元素的文本数据时
那么结果不包括子元素的文本数据。

已知问题
============

由于引擎问题,目前无法通过索引 0 访问
子元素:$object->property[0]。
php at keith tyler dot com
14 年前
[编辑注:但是,SimpleXMLIterator 类确实实现了这些方法。]

虽然 SimpleXMLElement 声称是可迭代的,但它似乎没有正确地实现标准的 Iterator 接口函数,如 ::next 和 ::reset。因此,虽然 foreach() 可以工作,但 next()、current() 或 each() 等函数似乎无法按预期工作——指针似乎从未移动或一直被重置。
radams at circlepix com
15 年前
要测试元素是否存在

<?php

$xml
= <<<EOT
<?xml version='1.0' standalone='yes'?>
<root>
<test1></test1>
<test2 />
<test4> </test4>
</root>
EOT;

$xmlDoc = new SimpleXMLElement($xml);

echo
"Test1: \n";
var_dump($xmlDoc->test1);
echo
"\n(" . (bool)$xmlDoc->test1 . ")";
echo
"\n\n";

echo
"Test2: \n";
var_dump($xmlDoc->test2);
echo
"\n(" . (bool)$xmlDoc->test2 . ")";
echo
"\n\n";

echo
"Test3: \n";
var_dump($xmlDoc->test3);
echo
"\n(" . (bool)$xmlDoc->test3 . ")";
echo
"\n\n";

echo
"Test4: \n";
var_dump($xmlDoc->test4);
echo
"\n(" . (bool)$xmlDoc->test4 . ")";
echo
"\n\n";

?>

test1、test2 和 test3 的 var_dumps 相同,但 (bool) 测试对 test1 和 test2 给出 '1',而对 test3 给出 ''。
To Top