使用 cdata PHP SimpleXML 解析 xml feed


Parsing xml feed with cdata PHP SimpleXML

我正在使用php将rss提要解析为json。

使用以下代码

我的 JSON 输出包含来自项目元素的描述之外的数据,但标题和链接数据未提取

  • 问题是一些不正确的CDATA或我的代码没有正确解析它的地方。

XML在这里

$blog_url = 'http://www.blogdogarotinho.com/rssfeedgenerator.ashx';
$rawFeed = file_get_contents($blog_url);
$xml=simplexml_load_string($rawFeed,'SimpleXMLElement', LIBXML_NOCDATA);
// step 2: extract the channel metadata
$articles = array();    
// step 3: extract the articles
foreach ($xml->channel->item as $item) {
    $article = array();
    $article['title'] = (string)trim($item->title);
    $article['link'] = $item->link;      
    $article['pubDate'] = $item->pubDate;
    $article['timestamp'] = strtotime($item->pubDate);
    $article['description'] = (string)trim($item->description);
    $article['isPermaLink'] = $item->guid['isPermaLink'];        
    $articles[$article['timestamp']] = $article;
}
echo json_encode($articles);

我认为您只是浏览器隐藏标签的受害者。让我解释一下:您的输入提要中实际上没有<![CDATA[ ]]>标签,<>实际上是在 rss 流的原始源中编码的实体,在浏览器中的 rss 链接上按 ctrl+u,您将看到:

<?xml version="1.0" encoding="utf-16"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.0">
  <channel>
    <description>Blog do Garotinho</description>
    <item>
      <description>&lt;![CDATA[&lt;br&gt;
          Fico impressionado com a hipocrisia e a falsidade de certos políticos....]]&gt;
      </description>
      <link>&lt;![CDATA[http://www.blogdogarotinho.com.br/lartigo.aspx?id=16796]]&gt;</link>
...
      <title>&lt;![CDATA[A bancada dos caras de pau]]&gt;</title>
    </item>

如您所见,例如,<title>以一个&lt;开头,当 simplexml 为您的 json 数据返回它时,该<将变为。现在,如果您在浏览器中查找打印的 json 数据,您的浏览器将看到以下内容:

"title":"<![CDATA[A bancada dos caras de pau]]>"

它不会被呈现,因为它在标签内。描述似乎显示出来,因为它在某个时候有一个<br>标签,它结束了第一个"标签",因此您可以看到输出的其余部分。

如果您按ctrl +u,您应该看到按预期打印的输出(我自己使用了命令行php文件,并没有首先注意到这一点(。

试试这个演示:

  • "title"后似乎有空的""
    http://codepad.viper-7.com/ZYpaS1
  • 但是,如果我在json_encode()周围放一个htmlspecialchars()
    http://codepad.viper-7.com/1nHqym 它们变得"可见"。

您可以尝试通过在解析后简单地用简单的preg_replace()替换它们来摆脱这些:

function clean_cdata($str) {
    return preg_replace('#(^'s*<!'[CDATA'[|']']>'s*$)#sim', '', (string)$str);
}

如果 CDATA 块位于各个标记的开头或结尾,这应该会处理它们。你可以像这样在foreach()循环中抛出调用这个:

// ....
$article['title'] = clean_cdata($item->title);
// ....