这不是不一致的行为吗? (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 &amp; Four');
$a->d = 'Five & Six';

print($a->asXML());

渲染:
<?xml version="1.0"?>
<a b="One &amp; Two">
    <c>Three &amp; Four</c>
    <d>Five &amp; Six</d>
</a>

在bugs.php.net上,他们拒绝了所有关于此的提交,说这是一项功能。为什么会这样呢?顺便说一句,文档中没有关于SimpleXMLElement转义文本值的差异的任何信息。

谁能说服我这是可能的最佳API设计决策?

最佳答案

为了确保我们在同一页面上,您有三种情况。

  • 使用addAttribute
  • 将&符插入属性
  • 使用addChild
  • 将&符插入元素
  • 通过重载
  • 将“&”号插入元素

    是2和3之间的差异让您感到困惑。为什么addChild不会自动转义与号,而将属性添加到对象并设置其值会导致自动转义与号?

    根据我的直觉,并受this bug的支持,这是一个有意的设计决策。属性重载($ a-> d ='Five&Six';;)旨在作为“对我来说是转义符”的处理方式。 addChild方法的目的是“完全添加我告诉您要添加的内容”方法。因此,无论您需要哪种行为,SimpleXML都可以满足您的需求。

    假设您有一个文本数据库,其中所有“&”号都已转义。自动转义不适用于您。那就是您要使用addChild的地方。或者说您需要在文档中插入一个实体
    $a = simplexml_load_string('<root></root>');
    $a->b = 'This is a non-breaking space &nbsp;';
    $a->addChild('c','This is a non-breaking space &nbsp;');
    print $a->asXML();
    

    这就是该漏洞中的PHP开发人员所主张的。当您需要在文件中插入“&”号而不会被转义时,addChild的行为旨在提供“更简单,更可靠”的支持。

    当然,这确实使我们处于我提到的第一种情况下,即addAttribute方法。 addAttribute方法可以使转义与号。因此,我们现在可以将不一致声明为
  • addAttribute方法转义与号
  • addChild方法不会转义与符号
  • 此行为有些不一致。合理的是,用户希望SimpleXML上的方法以一致的方式对事物进行转义

  • 然后,这暴露了SimpleXML api的实际问题。理想的情况是

    元素对象上的
  • 属性重载转义了&符号
  • 属性对象上的
  • 属性重载转义了&符号
  • addChild方法不会转义与号
  • addAttribute方法不会转义与号

  • 但是,这是不可能的,因为SimpleXML没有属性对象的概念。 addAttribute方法是(似乎是?)添加属性的唯一方法。因此,事实证明(似乎?)SimpleXML无法使用实体创建属性。

    所有这些都揭示了简单 XML的悖论。该API背后的想法是提供一种与复杂的事物进行交互的简单方法。

    该团队可以添加一个SimpleXMLAttribute对象,但这又增加了一层复杂性。如果要多个对象层次结构,请使用DomDoument。

    该团队可以在addAttribute和addChild方法中添加标志,但是标志会使API更加复杂。

    真正的教训在这里吗?也许简单很难,而在截止日期之前简单甚至更难。我不知道是否是这种情况,但是使用SimpleXML似乎有人从一个简单的主意开始(使用属性重载使XML文档的创建变得容易),然后根据出现的问题/功能请求进行调整。

    实际上,我认为这里的真正教训是仅使用JSON;)

    关于php - SimpleXMLElement处理addChild和addAttribute中的文本值的基本原理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/552957/

    10-09 19:28