扩展PHP的SimpleXMLElement

时间:2017-05-26 13:03:03

标签: php xml

我正在向外部供应商发送XML文档,其中一个在解析XML时遇到问题,因为XML内容中存在单引号和双引号。我知道根据官方的XML规范,这些只需要在属性中使用时进行转义,但我认为扩展PHP的SimpleXMLElement以使其转义为引用并不会太困难。此情况并非如此。我的第一次尝试是这样的:

<?php
class BetterXMLElement extends SimpleXMLElement
{
    public function __set($name, $value)
    {
        echo "called __set with $name and $value";
        $this->addChild($name, $value);
    }

    public function addChild($name, $value=null, $ns=null)
    {
        $new_value = strtr($value, [
            '&' => '&amp;',
            '"' => '&quot;',
            "'" => '&apos;',
        ]);
        echo "New Value: $new_value\n";
        parent::addChild($name, $new_value, $ns);
    }
}

$xml = new BetterXMLElement('<?xml version="1.0" encoding="UTF-8"?><TRANSACTION></TRANSACTION>');
$xml->COST = "apos: ', amp: &, quot: \"";
$xml->addChild('PRODUCT', "apos: ', amp: &, quot: \"");
echo $xml->asXML();

以上代码输出:

New Value: apos: &apos;, amp: &amp;, quot: &quot;
<?xml version="1.0" encoding="UTF-8"?>
<TRANSACTION><COST>apos: ', amp: &amp;, quot: "</COST><PRODUCT>apos: ', amp: &amp;, quot: "</PRODUCT></TRANSACTION>

这对我来说是:

  1. __set中的回声没有被调用,正如我预期的那样,当我设置COST时。为什么这不起作用?
  2. 我在设置PRODUCT时调用addChild上的覆盖,但是当调用asXML时,引号的HTML实体会被转换回来。它为什么这样工作?有没有办法禁用它?

2 个答案:

答案 0 :(得分:0)

不要使用简单的xml - 这是垃圾!

而是尝试DOMDocument()!

$dom = new DOMDocument();
$hello = $dom->createElement('hello');
$hello->setAttribute('such', 'wow');
$text = new DOMText('This & That');
$hello->appendChild($text);
$dom->appendChild($hello);
echo $dom->saveXML();

这将创建以下内容:

<?xml version="1.0"?> <hello such="wow">This &amp; That</hello>

答案 1 :(得分:0)

据我所知,由于libxml2的固有设计,没有干净的内置方法来完成我需要使用SimpleXMLElement或DOMDocument。我最终在XML处理之前用占位符替换必要的字符(例如,单引号被替换为“{quot}”),然后在XML输出中使用适当的HTML实体交换这些占位符。

另外,正如先前评论中指出的那样,SimpleXMLElement不是普通的PHP类,这就是我的覆盖尝试失败的原因。