代码之家  ›  专栏  ›  技术社区  ›  Ivan Krechetov

SimpleXMLElement处理addChild和addAttribute中文本值的基本原理

  •  39
  • Ivan Krechetov  · 技术社区  · 17 年前

    这不是一种前后矛盾的行为吗?(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>
    

    6 回复  |  直到 17 年前
        1
  •  85
  •   xylar    9 年前

    为了确保我们的观点一致,你有三种情况。

    1. 使用addAttribute在属性中插入符号AND

    2. 使用addChild在元素中插入符号AND

    3. 通过属性重载将符号和插入到元素中

    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();
    

    当然,这给我们留下了我提到的第一种情况,addAttribute方法。addAttribute方法 逃出安号。因此,我们现在可以将不一致性声明为

    1. addAttribute方法转义符号AND
    2. addChild方法 逃逸符
    3. 方法

    这就暴露了SimpleXML api的真正问题。这里的理想情况是

    1. 元素对象上的属性重载将转义符号AND
    2. 属性对象上的属性重载将转义符号AND
    3. addChild方法不转义符号AND
    4. addAttribute方法不转义符号

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

    所有这些都揭示了这一理论的悖论 易于理解的 XML。这个API背后的想法是提供一种简单的方式来与复杂的东西进行交互。

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

    真正的教训是什么?也许简单就很难,在最后期限前简单就更难了。我不知道情况是否如此,但对于SimpleXML,似乎有人从一个简单的想法开始(使用属性重载来简化XML文档的创建),然后随着问题/功能请求的出现进行调整。

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

        2
  •  16
  •   Mathias Weitz    13 年前

    $job->addChild('industrycode')->{0} = $entry1;
    $job->addChild('industrycode')->{0} = $entry2;
    $job->addChild('industrycode')->{0} = $entry3;
    
        3
  •  10
  •   Daniel    16 年前

    “假设您有一个文本数据库,其中所有的符号都已转义。”

    addChild()不为您的文本编码是完全违反直觉的。API中有什么地方不能保护您不受此影响?如果在一个值中使用双引号,这就像json_encode()barfing。

    无论如何,回答最初的问题:显然,我也认为这不是一个好的决定。我确实认为这与PHP的许多设计决策是一致的,即实现某人关于什么是“更快”的想法,而不是正确的想法。

        4
  •  7
  •   pmaruszczyk    13 年前

    转义字符的要求 & < Character Data and Markup 而不是如前面的回答所述,在属性值规范化部分中 .

    To quote the XML Spec . :

    &amp; &lt; 分别“

        5
  •  6
  •   Graham Lexie    14 年前

    艾伦·斯托姆(Alan Storm)对这个问题有一个很好的描述,但是他所描述的悖论有一个简单的解决方案。addChild()方法可以有一个可选的布尔参数,用于确定是否自动转义字符。所以,我仍然相信这只是一个(非常)糟糕的设计选择。

    一些 字符(即小于和大于符号)。这将误导使用该方法的开发人员,使他们相信它通常会逃避字符。

        6
  •  0
  •   Michael Borgwardt    17 年前

    我相信这是由于 Attribute-Value Normalization 这是XML规范所要求的。

    推荐文章