【问题标题】:PHP, SimpleXML, decoding entities in CDATAPHP,SimpleXML,解码 CDATA 中的实体
【发布时间】:2012-12-20 20:01:54
【问题描述】:

我遇到以下行为:

$xml_string1 = "<person><name><![CDATA[ Someone&#039;s Name ]]></name></person>";
$xml_string2 = "<person><name> Someone&#039;s Name </name></person>";

$person = new SimpleXMLElement($xml_string1);
print (string) $person->name; # Someone&#039;s Name

$person = new SimpleXMLElement($xml_string2);
print (string) $person->name; # Someone's Name

$person = new SimpleXMLElement($xml_string1, LIBXML_NOCDATA);
print (string) $person->name; # Someone&#039;s Name

php 文档说 NOCDATA “将 [s] CDATA 合并为文本节点”。对我来说,这意味着 CDATA 将被视为与文本节点相同 - 或者第三个示例的行为现在将与第二个示例相同。

我无法控制 XML(它是来自外部源的提要),否则我只会删除 CDATA 标记,因为它什么都不做并破坏了我想要的行为。

为什么上面的例子会有这样的行为?有没有办法让 SimpleXML 以与处理文本节点相同的方式处理 CDATA 节点? “将 CDATA 合并为文本节点”实际上做了什么,因为我似乎不理解该选项?

我目前正在提取数据后进行解码,但上面的示例对我来说仍然没有意义。

【问题讨论】:

  • print 具有字符串上下文,在这种情况下您不需要强制转换为字符串。
  • @hakre 但print(更常写成echo)很可能在调试时用作替身,然后用其他东西代替,所以我会说这是一个好习惯始终进行字符串转换以避免以后的混淆。

标签: php xml simplexml cdata libxml2


【解决方案1】:

XML 中 CDATA 部分的目的是“按原样”封装文本块,否则需要对特殊字符(特别是 &gt;&lt;&amp;amp;)进行转义。包含字符 &amp;amp; 的 CDATA 部分与包含 &amp;amp; 的普通文本节点相同。

如果解析器提出忽略这一点,并假装所有 CDATA 节点实际上只是文本节点,那么只要有人提到“P&O Cruises”,它就会立即中断——&amp;amp; 根本不可能出现在它的拥有(而不是 &amp;amp;&amp;somethingElse;)。

LIBXML_NOCDATA 实际上对 SimpleXML 毫无用处,因为(string)$foo 巧妙地将任何文本序列和 CDATA 节点组合成一个普通的 PHP 字符串。 (人们经常没有注意到这一点,因为print_r 没有。)对于更系统的访问方法(例如 DOM)不一定如此,您可以在其中将文本节点和 CDATA 节点作为自己的对象来操作。

它的有效作用是遍历文档,无论在哪里遇到 CDATA 部分,它都会获取内容,将其转义,然后将其作为普通文本节点放回,或者将其与任何文本节点“合并”到边。表示的文本是相同的,只是以不同的方式存储在文档中;如果您导出回 XML,您可以看到不同之处,如下例所示:

$xml_string = "<person><name>Welcome aboard this <![CDATA[P&O Cruises]]> voyage!</name></person>";

$person = new SimpleXMLElement($xml_string);
echo 'CDATA retained: ', $person->asXML();
// CDATA retained: <?xml version="1.0"?>
// <person><name>Welcome aboard this <![CDATA[P&O Cruises]]> voyage!</name></person>

$person = new SimpleXMLElement($xml_string, LIBXML_NOCDATA);
echo 'CDATA merged: ', $person->asXML();
// CDATA merged: <?xml version="1.0"?>
// <person><name>Welcome aboard this P&amp;O Cruises voyage!</name></person>

如果您正在解析的 XML 文档包含一个实际包含实体的 CDATA 部分,您需要获取该字符串并完全独立于 XML 将其取消转义。这样做的一个常见原因(除了懒惰对理解不充分的库之外)是将 HTML 中标记的内容视为 XML 文档中的任何旧字符串,如下所示:

<Comment>
<SubmittedBy>IMSoP</SubmittedBy>
<Text><![CDATA[I'm <em>really</em> bad at keeping my answers brief <tt>;)</tt>]]></Text>
</Comment>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 2015-03-08
    • 2013-06-19
    相关资源
    最近更新 更多