在PHP中从XML中解析HTML标记

3

我正在尝试使用PHP中的simplexml_load_string函数来解析http://uk.news.yahoo.com/rss,并创建自己的RSS源(仅用于学习)。但我遇到了无法读取<description>标签内的HTML标签的问题。

目前我的代码如下:

$feed = file_get_contents('http://uk.news.yahoo.com/rss');
$rss = simplexml_load_string($feed);

//for each element in the feed
foreach ($rss->channel->item as $item) {
    echo '<h3>'. $item->title . '</h3>'; 

        foreach($item->description as $desc){

             //how to read the href from the a tag???

             //this does not work at all
             $tags = $item->xpath('//a');
             foreach ($tags as $tag) {
                 echo $tag['href'];
             }
       }
}

有什么方法可以提取每个HTML标签吗?
谢谢
3个回答

3

描述内容具有其特殊字符编码,因此它不被视为XML中的节点,而只是一个字符串。您可以对特殊字符进行解码,然后将HTML加载到DOMDocument中并执行所需操作。例如:

foreach ($rss->channel->item as $item) {
    echo '<h3>'. $item->title . '</h3>'; 

        foreach($item->description as $desc){

            $dom = new DOMDocument();
            $dom->loadHTML(htmlspecialchars_decode((string)$desc));

            $anchors = $dom->getElementsByTagName('a');
            echo $anchors->item(0)->getAttribute('href');
        }
}

XPath也可用于DOMDocument,详见DOMXPath

谢谢。我离答案很近,但还不够接近。这正是我要找的。谢谢。 - Adrian

1

RSS源的<description>元素包含HTML。如如何使用SimpleXML解析XML中的CDATA HTML内容?所述,您需要获取该元素(即HTML)的节点值,并在一个额外的解析器中解析它。

链接问题的已接受答案已经展示了这一点,对于SimpleXML来说,在您的情况下,无论该RSS源是使用CDATA还是实体,都不会起太大作用。

$feed = file_get_contents('http://uk.news.yahoo.com/rss');
$rss  = simplexml_load_string($feed);
$dom  = new DOMDocument(); // the HTML parser used for descriptions' HTML

foreach ($rss->channel->item as $item)
{
    echo '<h3>' . $item->title . '</h3>', "\n";

    foreach ($item->description as $desc)
    {
        $dom->loadHTML($desc);

        $html = simplexml_import_dom($dom)->body;

        echo $html->p->a['href'], "\n";
    }
}

优秀的输出:

...
<h3>Chantal nears hurricane strength in Caribbean</h3>
http://uk.news.yahoo.com/chantal-nears-hurricane-strength-caribbean-220149771.html
<h3>Placido Domingo In Hospital With Blood Clot</h3>
http://uk.news.yahoo.com/placido-domingo-hospital-blood-clot-215427742.html
<h3>Berlusconi's final tax fraud appeal hearing set for July 30</h3>
http://uk.news.yahoo.com/berlusconis-final-tax-fraud-appeal-hearing-set-july-214714122.html
<h3>China: Men Rescued From River Amid Floods</h3>
http://uk.news.yahoo.com/china-men-rescued-river-amid-floods-213005159.html
<h3>Snowden has not yet accepted asylum in Venezuela - WikiLeaks</h3>
http://uk.news.yahoo.com/snowden-not-yet-accepted-asylum-venezuela-wikileaks-190332291.html
<h3>Three US kidnap victims break silence</h3>
http://uk.news.yahoo.com/three-us-kidnap-victims-release-thankyou-video-093832611.html
...

希望这能有所帮助。与被接受的答案相反,我看不出为什么要应用htmlspecialchars_decode,实际上我很确定这会破坏事情。此外,我的示例展示了如何通过将DOMNode转换回SimpleXMLElement来访问更多子元素,一旦解析了HTML。


嗨。谢谢你。我喜欢你的答案,因为它给了我XML节点。感谢你抽出时间写下这些。两个答案都帮助我理解如何访问这些标签(值信息)。再次感谢。 - Adrian

0
在这里最好的做法是对$item使用var_dump()函数。
feed = file_get_contents('http://uk.news.yahoo.com/rss');
$rss = simplexml_load_string($feed);
foreach ($rss->channel->item as $item) {
    var_dump($item);
    exit;
}

一旦你这样做,你会看到你想要的值叫做“链接”。“因此,要打印出URL,您将使用以下代码:

echo $item->link;

然而,如果我只想获取Feed的描述,这种方法就不起作用了!因为我会得到描述标签内的所有内容(例如图片)。 - Adrian
啊,那是因为 RSS 中实际的“description”元素包含了一张图片。如果你只想要文本而不需要图片,我会用 strip_tags 函数来包裹整个描述。因此,仅打印出描述的代码将是:echo strip_tags($item->description); - John Crawford
很好,这个(就像你说的)只适用于描述(谢谢)。但是如果我想提取所有带有属性的元素呢?比如说在这种情况下图片的 src 或者图片的 width - Adrian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接