我在网上找到的每个xml迭代示例(包括PHP文档,W3Schools和堆栈溢出搜索)都假定我们提前知道了结构。我想创建一个循环,该循环尽可能深入每个分支,并仅返回其找到的节点名称和值。例如:
<za-lord>
<orderid>dresden1234</orderid>
<customer>toot-toot</customer>
<pizza>
<sauce>marinara</sauce>
<crust>thin</crust>
<toppings>
<cheese>extra</cheese>
<veg>
<onions>yes</onions>
<peppers>extra</peppers>
<olives>no</olives>
</veg>
<meat>
<groundbeef>yes</groundbeef>
<ham>no</ham>
<sausage>no</sausage>
</meat>
</toppings>
</pizza>
</za-lord>
那么,我正在寻找的是:
orderid = dresden1234
customer = toot-toot
sauce = marinara
crust = thin
cheese = extra
onions = yes
peppers = extra
olives = no
groundbeef = yes
ham = no
sausage = no
我现在已经花了几个小时来编写代码示例,在 foreach 上测试了不同的变体,而简短的版本是什么也没让我得到我想要的东西。事先不知道其结构,是否可以递归地迭代上面的xml并使用SimpleXML返回节点名称和值,如果可以,怎么办?
答案 0 :(得分:0)
您可以使用SimpleXMLIterator
对象并对其进行递归以获取所有节点值:
function list_nodes($sxi) {
for($sxi->rewind(); $sxi->valid(); $sxi->next() ) {
if ($sxi->hasChildren()) {
list_nodes($sxi->current());
}
else {
echo $sxi->key() . " = " . $sxi->current() . "\n";
}
}
}
$sxi = new SimpleXMLIterator($xmlstr);
list_nodes($sxi);
输出:
orderid = dresden1234
customer = toot-toot
sauce = marinara
crust = thin
cheese = extra
onions = yes
peppers = extra
olives = no
groundbeef = yes
ham = no
sausage = no
更新
如果您的xml可以具有名称空间,则必须采取更复杂的方法,检查文档中每个名称空间中每个节点的子代:
function list_children($node, $names) {
$children = false;
foreach ($names as $name) {
if (count($node->children($name))) {
$children = true;
foreach ($node->children($name) as $child) {
list_children($child, $names);
}
}
}
if (!$children) {
echo $node->getName() . " = $node\n";
}
}
$xml = new SimpleXMLElement($xmlstr);
list_children($xml, array_merge(array(''), $xml->getNamespaces(true)));
输出(对于演示xml,与问题相同,但添加了名称空间):
orderid = dresden1234
customer = toot-toot
sauce = marinara
crust = thin
cheese = extra
onions = yes
peppers = extra
olives = no
ham = no
sausage = no
groundbeef = yes