这不是一种不一致的行为吗? (PHP 5.2.6)
<?php
$a = new SimpleXMLElement('<a/>');
$a->addAttribute('b', 'One & Two');
//$a->addChild('c', 'Three & Four'); -- results in "unterminated entity reference" warning!
$a->addChild('c', 'Three & Four');
$a->d = 'Five & Six';
print($a->asXML());
渲染:
<?xml version="1.0"?>
<a b="One & Two">
<c>Three & Four</c>
<d>Five & Six</d>
</a>
在bugs.php.net,他们拒绝所有关于此的提交,称这是一个功能。为什么会这样?顺便说一句,文档中没有任何关于SimpleXMLElement转义文本值的差异。
有人能说服我这是最好的API设计决策吗?
答案 0 :(得分:79)
为了确保我们在同一页面上,您有三种情况。
使用addAttribute
使用addChild
通过属性重载将&符号插入元素
这是2和3之间的差异让你陷入困境。为什么addChild不会自动转义&符号,而为对象添加属性并设置其值会自动转义&符号吗?
基于我的直觉,并受this bug的鼓舞,这是一个刻意的设计决定。属性重载($ a-&gt; d ='Five&amp; Six';)旨在成为“逃避&符号”的做事方式。 addChild方法意味着“正好添加我告诉你添加的方法”。因此,无论您需要哪种行为,SimpleXML都可以满足您的需求。
假设您有一个文本数据库,其中所有的&符已经被转义。自动转义在这里对你不起作用。这就是你使用addChild的地方。或者假设您需要在文档中插入实体
$a = simplexml_load_string('<root></root>');
$a->b = 'This is a non-breaking space ';
$a->addChild('c','This is a non-breaking space ');
print $a->asXML();
这就是那个bug中的PHP Developer所倡导的。 addChild的行为旨在提供“不太简单,更强大”的支持,当您需要在文档中插入&符号而不进行转义时。
当然,这确实让我们得到了我提到的第一种情况,即addAttribute方法。 addAttribute方法执行转义&符号。因此,我们现在可以将不一致性说明为
这样就暴露了SimpleXML api的真正问题。这里理想的情况是
这是不可能的,因为SimpleXML没有属性对象的概念。 addAttribute方法是(似乎是?)添加属性的唯一方法。因此,事实证明(似乎?)SimpleXML无法用实体创建属性。
所有这些都揭示了简单 XML的悖论。这个API背后的想法是提供一种与事物相互作用的简单方法,结果证明是复杂的。
团队可以添加一个SimpleXMLAttribute对象,但这是一个复杂的附加层。如果需要多个对象层次结构,请使用DomDoument。
团队可以在addAttribute和addChild方法中添加标志,但标志会使API更复杂。
真正的教训在这里?也许这很简单很难,而且在截止日期之前简单就更难了。我不知道是否是这种情况,但是使用SimpleXML似乎有人从一个简单的想法开始(使用属性重载来简化XML文档的创建),然后在问题/功能请求进入时进行调整
实际上,我认为这里的真正教训是只使用JSON;)
答案 1 :(得分:16)
这是我的解决方案,特别是这解决了添加几个具有相同标记名称的子项
$job->addChild('industrycode')->{0} = $entry1;
$job->addChild('industrycode')->{0} = $entry2;
$job->addChild('industrycode')->{0} = $entry3;
答案 2 :(得分:10)
“假设您有一个文本数据库,其中所有的&符号都已被转义。”
如果你这样做,你做错了。数据应以最准确的形式存储,而不是针对您当前使用的任何类型的输出。如果您实际在数据库中存储(有效)HTML的blob,情况会更糟。使用addChild()并再次获取数据将破坏您的HTML;没有明智的图书馆表现出如此可怕的不对称。
addChild()不会为您编码文本完全违反直觉。 API中有什么意义不能保护您免受此影响?如果你在一个值中使用双引号就像json_encode()barfing。
无论如何,要回答原来的问题:显然,我也认为这不是一个好的决定。我认为这与许多PHP的设计决策是一致的,这是为了满足某人对“更快”的想法,而不是正确的。
答案 3 :(得分:7)
转义字符&
和<
的要求在Character Data and Markup部分中提供,而不是在属性值规范化部分中提供,因为先前的答案陈述强>
<强> To quote the XML Spec 强>:
“和号字符(&amp;)和左尖括号(&lt;)绝不能以字面形式出现,除非用作标记分隔符,或用于注释,处理指令或CDATA部分。它们在其他地方需要,它们必须使用数字字符引用或字符串分别&
和<
进行转义“
答案 4 :(得分:5)
由于addChild()方法的文档没有任何引用所以问题(尽管在讨论中),这使得混淆更加复杂。此外,该方法转义一些字符(即小于和大于符号)。这将误导使用该方法的开发人员相信它一般会逃脱字符。
答案 5 :(得分:0)
我认为这是由XML规范要求的Attribute-Value Normalization引起的。