草庐IT

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

coder 2024-04-18 原文

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/

有关php - SimpleXML 子属性在有和没有命名空间时表现不同的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  7. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  10. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

随机推荐