Xpath-запрос для HTML-таблицы в XML в PHP DOMDocument

У меня есть 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://img.ruphp.com/php/example.jpg"/> </item> </channel> </rss> 

Здесь элемент table html встроен в XML, и это меня пугает.

Теперь я хочу выбрать значения текстового узла для //channel/item/title и href для //channel/item/description/table/tr/td[1]/a[1] (с текстовым value = "[link]" узла value = "[link]" )

Выше во втором случае я ищу значение 2а (с текстовым узлом value = "[link]" ), внутри 2-го td внутри tr , table , description , item , channel .

Я использую PHP DOMDocument();

Я искал идеальное решение для этого в течение 2 дней, не могли бы вы сообщить мне, как это произойдет?

Также мне нужно подсчитать общее количество элементов в фиде, прямо сейчас я делаю так:

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

И мне также нужна ссылка ссылки для правил селектора запросов XPath.

Заранее спасибо! 🙂

Вы написали, что хотите получить длину набора результатов следующего запроса:

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

Я предполагаю, что здесь $xpathvar имеет тип DOMXPath . Если это так, оно имеет свойство длины, как описано здесь . Вместо использования foreach просто используйте:

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

Теперь я хочу выбрать значения текстового узла для //channel/item/title

Который вы можете получить с помощью выражения //channel/item/title/text() .

и значение href для //channel/item/description/table/tr/td[1]/a[1] (с текстовым узлом 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 

который находит первый элемент в дереве, у которого есть значение (текстовый узел), который является "[link]" .

Выше во втором случае я ищу значение 2а (с текстовым узлом value = "[link]" ), внутри 2-го td внутри tr , table , description , item , channel .

Не уверен, что это был отдельный вопрос или означало объяснение предыдущего. Независимо от того, ответ так же, как и в предыдущем, если вы явно не хотите искать 2-й a т. Д. (Т. Е. Искать по положению), и в этом случае вы можете использовать числовые предикаты.


Примечание: вы запускаете большинство своих выражений с помощью //expr , что по существу означает: поиск всего дерева на любой глубине для выражения expr . Это потенциально дорого, и если все, что вам нужно, это (относительный) корневой узел, для которого вы знаете начальную точку или выражение, лучше и гораздо более эффективно использовать прямой путь. В вашем случае вы можете заменить //channel для /*/channel (потому что он является первым под корневым элементом).

Я, наконец, смогу заставить его работать с кодом ниже

 $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>"; } } 

Я благодарю Абеля, ваша помощь была очень полезной для решения поставленных задач. 🙂