PHP RSS XML синтаксический анализ, фильтрация и повторное отображение - PullRequest
0 голосов
/ 16 июня 2020

Я загружаю канал RSS XML в PHP с DOMDocument. Это нормально работает. Мне нужно проанализировать мои XML, найти определенные c значения, а затем снова отобразить только определенные узлы.

XML выглядит так ...

<rss version="2.0">
  <channel>
  <title>Title</title>
  <link></link>
  <item>
    <title>Title #1</title>
    <description>Here I want to filter</description>
  </item>
  <item>
    <title>Title #2</title>
    <description>Should not be displayed</description>
  </item>
</channel>

Я хочу выполнить поиск внутри тега описания, и если ключевое слово было найдено, я хочу отобразить item. Если он не найден, я хочу удалить родительский item.

Это то, что я пробовал до сих пор ...

<?php

header('Content-Type: text/xml');

// Load our XML document
$rss = new DOMDocument();
$rss->load('https://myurl');

$description = $rss->getElementsByTagName('description');

foreach ($description as $node) {
    $s = $node->nodeValue;

    if (strpos($s, 'filter') !== false)
    {
      //found the keyword, nothing to delete
    }
    else
    {
      //didnt find it, now delete item
      $node->parentNode->parentNode->removeChild($node->parentNode);
    }
}

echo $description->saveXml();

Я пытаюсь получить все узлы описания, проверьте, содержат ли они строку, а если нет, удалите родителя. Поиск String работает, но удаление узла нет. Если я повторю свой XML, ничего не изменилось.

1 Ответ

1 голос
/ 16 июня 2020

getElementsByTagName() вернет «живой» результат. Он изменится, если вы измените документ. Вы можете использовать iterator_to_array(), чтобы сделать стабильную копию.

Другой вариант - использовать выражения Xpath для извлечения определенных c узлов.

$document = new DOMDocument();
$document->loadXML($xmlString);
$xpath = new DOMXpath($document);

// fetch items that contain "filter" in their description
$items = $xpath->evaluate('/rss/channel/item[contains(description, "filter")]');
foreach ($items as $item) {
    // dump the title child element text content
    var_dump($xpath->evaluate('string(title)', $item));
} 

// fetch items that do not contain "filter" in their description
$items = $xpath->evaluate('/rss/channel/item[not(contains(description, "filter"))]');
foreach ($items as $item) {
    // remove item element
    $item->parentNode->removeChild($item);
} 
echo $document->saveXML();

Вывод:

string(8) "Title #1"
<?xml version="1.0"?>
<rss version="2.0">
  <channel>
  <title>Title</title>
  <link/>
  <item>
    <title>Title #1</title>
    <description>Here I want to filter</description>
  </item>

</channel>
</rss>
...