我遇到以下行为:
$xml_string1 = "<person><name><![CDATA[ Someone's Name ]]></name></person>"; $xml_string2 = "<person><name> Someone's Name </name></person>"; $person = new SimpleXMLElement($xml_string1); print (string) $person->name; # Someone'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's Name
php文档说NOCDATA“将CDATA合并为文本节点”。对我来说,这意味着CDATA将与文本节点一样对待-或第3个示例的行为现在与第2个示例相同。
我没有对XML的控制权(这是来自外部源的提要),否则我将删除CDATA标记,因为它不执行任何操作并破坏了我想要的行为。
上面的示例为什么会表现出这种方式?有什么方法可以使SimpleXML处理CDATA节点的方式与处理文本节点的方式相同?因为我似乎不了解该选项,所以“将CDATA合并为文本节点”实际上是做什么的?
在提取数据后,我目前正在解码,但是上面的示例对我来说仍然没有意义。
CDATA节的XML的目的是封装的文本块“为是”,否则将需要特殊字符(特别是>,<和&)进行转义。包含字符的CDATA节与包含的&普通文本节点相同&。
>
<
&
&
如果解析器提出要忽略这一点,并且假装所有CDATA节点实际上只是文本节点,那么一旦有人提到“ P&O Cruises”,它就会立即中断- &根本不能单独存在(而不是&,或&somethingElse;)。
&somethingElse;
该LIBXML_NOCDATA实际上是用SimpleXML漂亮没用,因为(string)$foo巧妙地结合了文本和CDATA节点的任何序列为普通PHP字符串。(人们经常注意到的东西,因为print_r没有。)对于诸如DOM之类的更系统的访问方法,这不一定是正确的,在DOM中,您可以独立地将文本节点和CDATA节点作为对象来操作。
LIBXML_NOCDATA
(string)$foo
print_r
它有效地做的是遍历文档,无论遇到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&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>