【问题标题】:Xpath query for HTML table within XML in PHP DOMDocumentPHP DOMDocument 中 XML 中 HTML 表的 Xpath 查询
【发布时间】:2015-09-07 20:55:35
【问题描述】:

我有一个具有以下树结构的 XML 文件。

<rss xmlns:dc="http://purl.org/dc/elements/1.1/"  xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
    <title>Videos</title>
    <link>https://www.example.com/r/videos/</link>
    <description>A long description of the video.</description>
    <image>...</image>
    <atom:link rel="self" href="http://www.example.com/videos/.xml" type="application/rss+xml"/>
    <item>
        <title>The most used Jazz lick in history.</title>
        <link>
        http://www.example.com/
        </link>
        <guid isPermaLink="true">
         http://www.example.com/
        </guid>
    <pubDate>Mon, 07 Sep 2015 14:43:34 +0000</pubDate>
    <description>
    <table>
        <tr>
            <td>
                <a href="http://www.example.com/">
                    <img src="http://www.example.com/.jpg" alt="The most used Jazz lick in history." title="The most used Jazz lick in history." />
                </a>
            </td>
            <td> submitted by 
                <a href="http://www.example.com/"> jcepiano </a>
                <br/>
                <a href="http://www.youtube.com/">[link]</a>
                <a href="http://www.example.com/">
                    [508 comments]
                </a>
            </td>
        </tr>
    </table>
    </description>
    <media:title>The most used Jazz lick in history.</media:title>
    <media:thumbnail url="http://example.jpg"/>
    </item>
</channel>
</rss>

这里,html table 元素嵌入在 XML 中,这让我很困惑。

现在我想选择//channel/item/title 的文本节点值和//channel/item/description/table/tr/td[1]/a[1] 的href 值(带有文本节点value = "[link]"

在第二种情况下,我正在寻找第二个a的值(带有文本节点value = "[link]"),在第二个td里面trtabledescriptionitem , channel.

我正在使用 PHP DOMDocument();

这两天我一直在寻找一个完美的解决方案,你能告诉我这是怎么发生的吗?

我还需要计算提要中的项目总数,现在我正在这样做:

...
$queryResult = $xpathvar->query('//item/title');
$total = 1;
foreach($queryResult as $result){
           $total++;
}
echo $title;

我还需要一个 XPath 查询选择器规则的参考链接。

提前致谢! :)

【问题讨论】:

  • 通过在标记名等内联代码元素周围使用``(反引号),可以更轻松地阅读和剖析英文文本中的代码。我已经更新了你的问题。
  • 感谢您的帮助和信息,下次我会记住的。

标签: php html xml xpath


【解决方案1】:

您写道,您想要以下查询的结果集的长度:

$queryResult = $xpathvar->query('//item/title');

我假设这里的$xpathvarDOMXPath 类型。如果是这样,它有一个length property as described here。不要使用foreach,只需使用:

$length = $xpathvar->query('//item/title')->length;

现在我想选择//channel/item/title 的文本节点值

您可以使用表达式//channel/item/title/text() 获得。

//channel/item/description/table/tr/td[1]/a[1] 的 href 值(带有文本节点 value = "[link]"

您在此处的表达式选择任何tr,其下的第一个td,然后是第一个a。但是第一个 a 在您的源中没有 "[link]" 的值。但是,如果您愿意,可以使用:

//channel/item/description/table/tr/td[1]/a[1]/@href

但看起来你更想要:

//channel/item/description/table/tr/td/a[. = "[link]"][1]/@href

在树中找到第一个a元素,其值(文本节点)为"[link]"

在第二种情况下,我正在寻找第二个a的值(带有文本节点value = "[link]"),在第二个td内部trtabledescriptionitem , channel.

不确定这是一个单独的问题还是要解释前一个问题。无论如何,答案与上一个相同,除非您明确要搜索第二个 a 等(即按位置搜索),在这种情况下您可以使用数字谓词。


注意:您的大部分表达式都以//expr 开头,这实质上意味着:在整个树的任意深度搜索表达式expr。这可能很昂贵,如果您只需要一个(相对)根节点,您知道其起点或表达式,那么使用直接路径会更好,性能也更高。在您的情况下,您可以将//channel 替换为/*/channel(因为它是根元素下的第一个)。

【讨论】:

  • 感谢您的回答,我在这里学到了很多东西。但是,我仍然在为几件事而苦苦挣扎。 items 元素在 XML 提要中重复多次。而且我需要根据上面提到的 Xpath 表达式来回显每个文本节点值。我该怎么做?
  • @Yogie,听起来你应该在 PHP 中使用 for-each(就像你已经展示过的那样),或者你应该使用 concat XPath 函数。通常,像您这样的任务是在 XSLT 中完成的,在这种情况下,它会变得更简单,尤其是。如果您还需要添加 HTML 标记。如果您无法弄清楚 PHP 部分,请考虑仅针对该问题提出一个新问题。
  • 感谢您花时间和精力回答,对不起,我是 XML 解析的新手,所以请多多包涵。因为我需要回显两个元素的节点值(如问题中所述),而不是一个,所以我认为最好使用 for 循环而不是foreach,因为foreach 只会回显一个节点值,在我们的案例,titlehref 用于“[link]”。
  • @Yogie,您可以访问节点集中节点的属性,请参阅documentation for DOMNodeList,其中也有几个示例。要从 XPath 中获取两个元素,请使用 nodename1 | nodename2,它单独选择两个元素,或者选择父元素,以便您可以访问子元素。
【解决方案2】:

我终于可以用下面的代码让它工作了

$url = "https://www.example.com/r/videos/.xml";
$feed_dom = new domDocument; 
$feed_dom->load($url); 
$feed_dom->preserveWhiteSpace = false;
$items = $feed_dom->getElementsByTagName('item');

foreach($items as $item){
    $title = $item->getElementsByTagName('title')->item(0)->nodeValue;
    $desc_table = $item->getElementsByTagName('description')->item(0)->nodeValue;
    echo $title . "<br>";

    $table_dom = new domDocument;
    $table_dom->loadHTML($desc_table);
    $xpath = new DOMXpath($table_dom);
    $table_dom->preserveWhiteSpace = false;
    $yt_link_node = $xpath->query("//table/tr/td[2]/a[2]");

    foreach($yt_link_node as $yt_link){

        $yt = $yt_link->getAttribute('href');
        echo $yt . "<br>";
        echo "<br>";
    }
}

感谢 Abel,您的帮助对完成任务非常有用。 :)

【讨论】:

    猜你喜欢
    • 2012-05-06
    • 1970-01-01
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    相关资源
    最近更新 更多