这不是一种不一致的行为吗?(PHP 5.2.6)
'); $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());
呈现:
Three & Four Five & Six
在bugs.php.net,他们拒绝所有提交的内容,称这是一个功能.为什么会这样?顺便说一句,文档中没有任何关于SimpleXMLElement转义文本值的差异.
任何人都可以说服我这是最好的API设计决策吗?
为了确保我们在同一页面上,您有三种情况.
使用addAttribute将&符插入属性中
使用addChild将&符插入元素中
通过属性重载将&符插入元素中
这是2和3之间的差异让你感到沮丧.为什么addChild不会自动转义&符号,而向对象添加属性并设置其值会自动转义&符号?
根据我的直觉,并受到这个错误的鼓舞,这是一个刻意的设计决定.属性重载($ a-> d ='Five&Six';)旨在成为"为我做逃避的&符号"的做事方式.addChild方法意味着"正好添加我告诉你添加的方法".因此,无论您需要哪种行为,SimpleXML都可以满足您的需求.
假设您有一个文本数据库,其中所有的&符号都已被转义.自动转义在这里对你不起作用.这就是你使用addChild的地方.或者假设您需要在文档中插入实体
$a = simplexml_load_string(''); $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方法确实转义了&符号.所以,我们现在可能会说不一致
addAttribute方法转义&符号
addChild方法不会转义&符号
这种行为有些不一致.用户期望SimpleXML上的方法以一致的方式逃避事情是合理的
然后,这暴露了SimpleXML api的真正问题.这里的理想情况是
元素对象上的属性重载转义&符号
属性对象上的属性重载转义&符号
addChild方法不会转义&符号
addAttribute方法不会转换&符号
但这是不可能的,因为SimpleXML没有属性对象的概念.addAttribute方法是(似乎是?)添加属性的唯一方法.因此,事实证明(似乎?)SimpleXML无法使用实体创建属性.
所有这些都揭示了Simple XML 的悖论.这个API背后的想法是提供一种与事物相互作用的简单方法,结果证明是复杂的.
团队可以添加一个SimpleXMLAttribute对象,但这是一个复杂的附加层.如果需要多个对象层次结构,请使用DomDoument.
团队可以在addAttribute和addChild方法中添加标志,但标志会使API更复杂.
真正的教训在这里?也许这很简单很难,而且在截止日期之前简单就更难了.我不知道是否是这种情况,但是使用SimpleXML似乎有人从一个简单的想法开始(使用属性重载来简化XML文档的创建),然后在问题/功能请求进入时进行调整.
实际上,我认为这里的真正教训是只使用JSON;)
这是我的解决方案,特别是这解决了添加几个具有相同标记名称的子项
$job->addChild('industrycode')->{0} = $entry1; $job->addChild('industrycode')->{0} = $entry2; $job->addChild('industrycode')->{0} = $entry3;
"假设你有一个文本数据库,其中所有的&符已被转义."
如果你这样做,你做错了.数据应以最准确的形式存储,而不是针对您当前使用的任何类型的输出.如果您实际在数据库中存储(有效)HTML的blob,情况会更糟.使用addChild()并再次获取数据将破坏您的HTML; 没有明智的图书馆表现出如此可怕的不对称性.
addChild()不会为您编码文本完全违反直觉.API中有什么意义不能保护您免受此影响?如果你在一个值中使用双引号就像json_encode()barfing.
无论如何,回答原来的问题:显然,我也认为这不是一个好的决定.我认为这与许多PHP的设计决策是一致的,这是为了满足某人对"更快"的想法,而不是正确的.
转义字符的要求&
,并<
在部分被设置字符数据和标记,而不是在部分属性值标准化,因为以前的答案的状态.
引用XML规范.:
"&符号(&)和左尖括号(<)绝不能以字面形式出现,除非用作标记分隔符,或用于注释,处理指令或CDATA部分.如果在其他地方需要它们,他们都必须用数字字符引用或字符串进行转义&
,并<
分别"
Alan Storm对这个问题有一个很好的描述,但是对于他描述的悖论有一个简单的解决方案.addChild()方法可以有一个可选的布尔参数,用于确定是否自动转义字符.所以,我仍然相信它只是一个(非常)糟糕的设计选择.
由于addChild()方法的文档没有任何引用所以问题(尽管在讨论中),这使得混淆更加复杂.此外,该方法逃避了一些字符(即小于和大于符号).这将误导使用该方法的开发人员相信它一般会逃脱字符.