将simplexmlelement转换为string以获得内部内容,但保持htmlspecialchars转义


cast simplexmlelement to string to get inner content but keep htmlspecialchars escaped

我有一个xmlfile:

$xml = <<<EOD
<?xml version="1.0" encoding="utf-8"?>
<metaData xmlns="http://www.test.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test">
<qkc6b1hh0k9>testdata&amp;more</qkc6b1hh0k9>
</metaData>
EOD;

现在我将它加载到一个simplexmlobject中,稍后我想获得"qkc6b1hh0k9"节点的内部

$xmlRootElem = simplexml_load_string( $xml );
$xmlRootElem->registerXPathNamespace( 'xmlns', "http://www.test.com/" );
// ...
$xPathElems = $xmlRootElem->xpath( './'."xmlns:qkc6b1hh0k9" );
$var = (string)($xPathElems[0]);
var_dump($var);

我期望得到字符串

testdata&amp;more

…但是我得到

testdata&more
  • 为什么simplexmlobject的__toString()方法将我的转义特殊字符转换为正常字符?我可以取消这个行为吗?
  • 我想出了一个临时解决方案,我觉得很脏,你说呢?

    (strip_tags ($ xPathElems[0] ->对asXML ()))

  • DOMDocument可以是另一种选择吗?

谢谢你对我问题的帮助!

编辑

问题解决了,问题不在simplexml的__toString方法中,它是在稍后使用带有addChild的字符串时出现的

如上所述的行为是完全正常的,正如你在答案中看到的那样…

只有当通过"addChild"将值添加到另一个xml文档时,才会出现

问题。由于addChild不会转义& (http://www.php.net/manual/de/simplexmlelement.addchild.php#103587),因此必须手动进行。

为什么simplexmlobject的__toString()方法将我的转义特殊字符转换为正常字符?我可以取消这个行为吗?

因为那些"特殊"字符实际上是字符的XML编码。使用字符串值将再次提供这些字符。这就是XML解析器的作用。

我想出了一个临时解决方案,我认为这是肮脏的,你说呢?

,摇摇欲坠。相反,我建议您使用相反的方法:XML编码字符串:

$var = htmlspecialchars($xPathElems[0]);
var_dump($var);

可以用DOMDocument替代吗?

不,作为SimpleXML,它是一个XML解析器,因此您也可以解码文本。这并不是完全正确的(您可以通过遍历所有子节点并选择字符数据旁边的实体节点来使用DomDocument,但是正如上面的htmlspecialchars()所概述的那样,它要做更多的工作)。

如果您通过任何相同的方法创建XML标记,并将其设置为包含字符串"testdata&more",则该字符串将被转义为testdata&amp;more。因此,唯一合乎逻辑的做法是将该字符串内容提取出来,使转义过程反转,从而得到您输入的文本。

问题是,为什么需要xml转义表示?如果你想要的元素的内容是作者的意图,那么__toString()是做正确的事情;在XML中表示该字符串的方法不止一种,但通常应该关心的是所表示的数据。

如果出于某种原因,您确实需要XML如何在特定实例中构造的详细信息,您可以使用更复杂的解析框架,例如DOM,它将testdata&amp;more分离为文本节点(包含"testdata")、实体节点(名称为"amp")和另一个文本节点(包含"more")。

另一方面,如果您只想把它放回另一个XML(或HTML)文档中,那么让SimpleXML正确地进行反转义,并在适当的时候重新转义。