SimpleXML 无法获取带有 ns 前缀的 CDATA

SimpleXML can't get CDATA with ns prefixes

在过去的几个小时里,我一直在努力从 xml 文件中获取 CDATA,尽管我已经尝试了显示的不同方法 here, here, and here

我的困境与通过 xenForo 的 RSS 提要检索线程数据有关。这是我尝试检索的 RSS 数据示例,除了检索 <content:encoded>.

外,一切正常

示例文件:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>News &amp; Announcements</title>
    <description>All of our important news and announcements will be here.</description>
    <pubDate>Fri, 26 Jun 2015 14:54:20 +0000</pubDate>
    <lastBuildDate>Fri, 26 Jun 2015 14:54:20 +0000</lastBuildDate>
    <generator>********* ****</generator>
    <link>https://***.****.****/forum/news/</link>
    <atom:link rel="self" type="application/rss+xml" href="https://***.****.****/forum/news/index.rss"/>
    <item>
      <title>Site under development.</title>
      <pubDate>Thu, 25 Jun 2015 05:49:43 +0000</pubDate>
      <link>https://***.****.****/threads/site-under-development.3/</link>
      <guid>https://***.****.****/threads/site-under-development.3/</guid>
      <author>invalid@example.com (*****)</author>
      <dc:creator>ShortCut Central</dc:creator>
      <content:encoded><![CDATA[Content to retrieve. <br /> Some more content a part of the same section]]></content:encoded>
    </item>
  </channel>
</rss>

我当前的代码看起来像

<?php
class SCC_Main_miscFuncs {
    public static function printMostRecentPost() {
        // Re-enable the below once we're ready to release
        //$rssUrl = func_get_arg(1);
        $rssUrl = 'https://www.shortcutcentral.org/indev.rss';
        $xml = simplexml_load_string(self::returnContents($rssUrl));
        $rawData = self::returnContents($rssUrl); // Properly contains the CDATA
        echo '<pre>';
        //echo (string) $xml->channel->item->encoded;
        //echo (string) $xml->channel->item->content;
        //var_dump($xml);
        echo '</pre>';
        //echo (string) $xml->channel->item;
        //echo $array[@attributes]['item']['link'];
        //echo $xml->message;
    }

    public static function returnContents($url){
        $curl_handle=curl_init();
        curl_setopt($curl_handle, CURLOPT_URL,$url);
        curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
        curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl_handle, CURLOPT_USERAGENT, 'ShortCut Central');
        $query = curl_exec($curl_handle);
        curl_close($curl_handle);
        return $query;
    }
} 

除了未解析的 $rawData 之外,似乎没有任何内容显示上述 CDATA。我觉得这可能是因为我没有正确调用它(对 XML 和名称空间和名称空间前缀来说是全新的),但它没有通过 var_dump 显示给了我......地狱。我看到了一些关于使用 XML children 的早期帖子,但我并不完全理解这个概念,这就是为什么如果我的解决方案需要 XML children,我将不胜感激。

谢谢!

另外可能值得一提的是,我的 php 代码是按原样组织的(类 和 public,静态函数),因此我可以将其用作xenForo 的附加组件。

您是正确的,return SimpleXML 中命名空间节点的一种方法是使用 SimpleXMLElement::children(),但您必须将命名空间作为其第一个参数传递。您可以传递完整的命名空间字符串 "http://purl.org/rss/1.0/modules/content/",但传递其前缀 "content" 更容易,然后提供 TRUE 作为第二个参数以通知 children() 您是传递前缀而不是完整字符串。

因此,在您的 $xml 对象上使用表达式,例如:

echo (string)$xml->channel->item->children('content', TRUE)->encoded;
// Prints:
// Content to retrieve. <br /> Some more content a part of the same section

使用在您的代码上下文中最有意义的任何方法来检索循环中的所有相关节点。

从命名空间节点中检索属性并没有太大不同。要获得 <atom:link href> 例如:

echo (string)$xml->channel->children('atom', true)->link->attributes()['href'];
// Prints
// https://***.****.****/forum/news/index.rss