使用cdata PHP SimpleXML解析xml feed

时间:2014-06-01 15:12:26

标签: php xml json simplexml

我正在使用php解析json的RSS源。

使用以下代码

我的json输出包含来自item元素的描述数据,但标题和链接数据未提取

  • 问题是在某些地方使用了不正确的CDATA,或者我的代码没有正确解析它。

xml是here

$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);

1 个答案:

答案 0 :(得分:2)

我认为你只是隐藏标签的浏览器的受害者。让我解释: 您的输入Feed中并没有<![CDATA[ ]]>个标记,<>实际上是在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文件,并没有先注意到这一点)。

试试这个演示:

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

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

如果它们位于各个标签的开头或结尾,则应该处理CDATA块。您可以在foreach()循环中调用此方法,如下所示:

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