У меня есть 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>"; } }
Я благодарю Абеля, ваша помощь была очень полезной для решения поставленных задач. 🙂