【问题标题】:SimpleXML: handle CDATA tag presence in node valueSimpleXML:处理节点值中存在的 CDATA 标记
【发布时间】:2017-06-22 13:41:14
【问题描述】:

解析XML文档时需要保存<![CDATA[]]>标签。

例如,我有节点:

<Dest><![CDATA[some text...]]></Dest>

在 xml 文件中可能存在没有 CDATA 的节点。

然后我循环处理所有节点:

$dom = simplexml_load_file($path);
foreach($dom->children() as $child) {
 $nodeValue = (string) $child;
}

因此,当我在上面的示例中处理节点时 - $nodeValue = some text...

但我需要$nodeValue = &lt;![CDATA[some text...]]&gt;

有什么办法吗?

文件示例:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
  <Params>
    <param>text</param>
    <anotherParam>text</anotherParam>
  </Params>
  <Content>
    <String>
      <Source>some another text</Source>
      <Dest>some another text 2</Dest>
    </String>
    <String>
      <Source>some another text 3</Source>
      <Dest><![CDATA[some text...]]></Dest>
    </String>
  </Content>
</Root>

【问题讨论】:

  • 你能举一个XML文件的例子吗?

标签: php simplexml cdata


【解决方案1】:

就像 SimpleXML 这样的解析器而言,&lt;![CDATA[ 不是 XML 元素文本内容的一部分,它只是该内容序列化的一部分。这里讨论了类似的混淆:PHP, SimpleXML, decoding entities in CDATA

您需要查看的是该元素的“内部 XML”,这在 SimpleXML 中很棘手(-&gt;asXML() 将为您提供“外部 XML”,例如 &lt;Dest&gt;&lt;![CDATA[some text...]]&gt;&lt;/Dest&gt;)。

你最好的选择是使用the DOM,它可以让你更多地访问文档的详细结构,而不是试图给你内容,所以区分“文本节点”和“CDATA 节点”。但是,值得仔细检查您是否确实需要它,因为对于 99.9% 的用例,您不应该关心是否有人向您发送了 &lt;foo&gt;bar &amp;amp; baz&lt;/foo&gt;&lt;foo&gt;&lt;![CDATA[bar &amp; baz]]&gt;&lt;/foo&gt;,因为根据定义它们代表相同的字符串。

【讨论】:

    【解决方案2】:

    如果你想将 CDATA 添加到所有没有它的元素,你可以这样做:

    $dom = simplexml_load_file($path);
    foreach($dom->children() as $child) {
         if(strpos((string) $child,'CDATA')){
             $nodeValue = (string) $child)
         }
         else {
             $nodeValue = "<![CDATA[".((string) $child)."]]>";
         }
     }
    

    你将拥有$nodeValue = '&lt;![CDATA[some text...]]&gt;'

    如果您只想拥有存在 CDATA 的元素,您可以这样做:

    $dom = simplexml_load_file($path);
    foreach($dom->children() as $child) {
         if(strpos((string) $child,'CDATA')){
             $nodeValue = (string) $child;
         }
     }
    

    你将拥有$nodeValue = '&lt;![CDATA[some text...]]&gt;'

    如果您想要没有 CDATA 的元素并添加它,您可以这样做:

    $dom = simplexml_load_file($path);
    foreach($dom->children() as $child) {
         if(!strpos((string) $child,'CDATA')){
             $notValue ="<![CDATA[".((string) $child)."]]>";
         }
     }
    

    你将拥有$nodeValue = '&lt;![CDATA[some another text 3]]&gt;'

    【讨论】:

    • 在 xml 文件中可能存在没有 CDATA 的节点
    • 你怎么知道必须有 CDATA 而没有?
    • @AndrewAndrew 哦,你有一个 xml 文件,其中一些值是 &lt;![CDATA[some text...]]&gt; 并使用你的算法删除 CDATA ?
    • 当我解析 xml 文件时,我对文件结构等一无所知。有些节点可能有 CDATA,有些可能没有,我不知道。但是在解析时,我需要处理它
    • @AndrewAndrew 好的,如果 node 包含 CDATA 你只需重写它,如果没有,你添加 CDATA ?
    猜你喜欢
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 2014-09-22
    • 2011-08-01
    • 1970-01-01
    • 2011-07-12
    • 2014-11-22
    相关资源
    最近更新 更多