当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《SimpleXMLElement在addChild和addAttribute中处理文本值的基本原理》经验,为你挑选了5个好方法。

这不是一种不一致的行为吗?(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设计决策吗?



1> Alan Storm..:

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

    使用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;)


先生,你真棒.感谢您对我无法弄清楚的事情的高质量解释.
"addAttribute方法是添加属性的唯一方法" - 这是*不正确*:`$ a-> b ['attr'] ='value';`.使用数组访问运算符,您可以创建,更改,并使用"unset"删除属性.但是,它取决于键:当键是一个整数时,它处理子元素,但是当键是一个字符串时,它处理属性.(注意:我做过最小的试验,所以我可能会错过一两个细节!)

2> 小智..:

这是我的解决方案,特别是这解决了添加几个具有相同标记名称的子项

$job->addChild('industrycode')->{0} = $entry1;
$job->addChild('industrycode')->{0} = $entry2;
$job->addChild('industrycode')->{0} = $entry3;



3> Daniel..:

"假设你有一个文本数据库,其中所有的&符已被转义."

如果你这样做,你做错了.数据应以最准确的形式存储,而不是针对您当前使用的任何类型的输出.如果您实际在数据库中存储(有效)HTML的blob,情况会更糟.使用addChild()并再次获取数据将破坏您的HTML; 没有明智的图书馆表现出如此可怕的不对称性.

addChild()不会为您编码文本完全违反直觉.API中有什么意义不能保护您免受此影响?如果你在一个值中使用双引号就像json_encode()barfing.

无论如何,回答原来的问题:显然,我也认为这不是一个好的决定.我认为这与许多PHP的设计决策是一致的,这是为了满足某人对"更快"的想法,而不是正确的.



4> Dimitre Nova..:

转义字符的要求&,并<在部分被设置字符数据和标记,而不是在部分属性值标准化,因为以前的答案的状态.

引用XML规范.:

"&符号(&)和左尖括号(<)绝不能以字面形式出现,除非用作标记分隔符,或用于注释,处理指令或CDATA部分.如果在其他地方需要它们,他们都必须用数字字符引用或字符串进行转义&,并<分别"



5> 小智..:

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

由于addChild()方法的文档没有任何引用所以问题(尽管在讨论中),这使得混淆更加复杂.此外,该方法逃避了一些字符(即小于和大于符号).这将误导使用该方法的开发人员相信它一般会逃脱字符.

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有