gpt4 book ai didi

php - SimpleXML 子属性在有和没有命名空间时表现不同

转载 作者:可可西里 更新时间:2023-10-31 23:30:10 26 4
gpt4 key购买 nike

SimpleXML examples page ,“Example #5 Using attributes”部分指出:

Access attributes of an element just as you would elements of an array.

以及 SimpleXMLElement::children() 中的示例#1使用 $element['attribute'] 语法访问 child 的属性;

向该代码添加命名空间,将禁用对属性的访问:

$xml = new SimpleXMLElement(
'<person xmlns:a="foo:bar">
<a:child role="son">
<a:child role="daughter"/>
</a:child>
<a:child role="daughter">
<a:child role="son">
<a:child role="son"/>
</a:child>
</a:child>
</person>');
foreach ($xml->children('a', true) as $second_gen) {
echo ' The person begot a ' . $second_gen['role'];
foreach ($second_gen->children('a', true) as $third_gen) {
echo ' who begot a ' . $third_gen['role'] . ';';
foreach ($third_gen->children('a', true) as $fourth_gen) {
echo ' and that ' . $third_gen['role'] . ' begot a ' . $fourth_gen['role'];
}
}
}
// results
// The person begot a who begot a ; The person begot a who begot a ; and that begot a
// expected
// The person begot a son who begot a daughter; The person begot a daughter who begot a son; and that son begot a son

这里有很多问题都指向相同的解决方案,即使用 SimpleXMLElement::attributes() 函数而不是作为数组访问,但没有人回答解释原因。

使用 namespace 时的这种不同行为是一个错误吗?文档是否过时?我们是否应该始终使用 SimpleXMLElement::attributes() 并避免推荐的类似数组的语法?

注意:我使用的是 PHP 5.5.9-1ubuntu4.9


相关问题

最佳答案

这样做的原因实际上与 SimpleXML 无关,而是与根据标准的 XML namespace 如何工作的一些令人惊讶的细节有关。

在您的示例中,您有一个使用前缀 a 声明的 namespace ,因此要声明该 namespace 中的属性,您必须在其名称前加上前缀 a: ,就像您处理元素一样:

<a:child a:role="daughter"/>

这似乎是一个常见的假设,即没有命名空间前缀的属性与它所在的元素位于同一命名空间中,但事实并非如此。上面的示例等同于您的示例:

<a:child role="daughter"/>

您可能会看到的另一种情况是默认(无前缀)命名空间:

<person xmlns="http://example.com/foo.bar"><child role="daughter" /></person>

这里,child 元素在 http://example.com/foo.bar 命名空间中,但是角色 属性仍然不是!正如在 this related question 中讨论的那样, relevant section of the XML Namespaces spec包括这个声明:

The namespace name for an unprefixed attribute name always has no value.

也就是说,没有命名空间前缀的属性永远不会出现在任何命名空间中,无论文档的其余部分是什么样子。

那么,这对 SimpleXML 有什么影响?

SimpleXML 的工作原理是在您使用 ->children()->attributes() 方法时更改“当前命名空间”,并从然后继续。

所以当你写的时候:

$children = $xml->children('a', true);

或:

$children = $xml->children('http://example.com/foo.bar');

“当前 namespace ”是 foo:bar->childElement['attribute'] 语法的后续使用将在此命名空间中查找 - 您无需调用 children() 每次都再次出现 - 但您的未加前缀的属性不会在那里找到,因为它们没有命名空间。

当你随后写:

$attributes = $children->attributes();

这与以下内容的解释方式相同:

$attributes = $children->attributes(null);

所以现在,“当前命名空间”是null。现在,当您查找没有 namespace 的属性时,您会找到它们。

关于php - SimpleXML 子属性在有和没有命名空间时表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30260452/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com