Как реализовать универсальный потоковый плеер

Мы будем подробно описывать этапы построения потокового плеера, признающего все форматы, используя XML-возможности PHP 5.
Для этого исследования необходимо знать структуру RSS-файла.

Эта расширяемая страница выполняется с помощью Ajax Extensible Page Xul.fr и фреймворка Anaa.

Структура RSS-файла

Любой файл синдикации содержит список элементов, статей, билетов или других документов и описание сайта, являющегося их источником, который называется каналом.
Для канала, как и для элементов, будут приведены заголовок и описание, а также URL.

Статьи или документы

Во всех форматах повторяются основные данные: и ссылка на статью, и заголовок, и резюме.

<item> 
    <title>Tutoriels RSS</title>
    <link>https://www.iqlevsha.ru/lecteur-de-flux.php</link>     
    <description>Tutoriels sur la construction et l'utilisation de flux RSS </description> 
</item>

Имена тегов отличаются в зависимости от формата. Другие данные могут быть представлены, например, дата выпуска, автор, логотип и т.д.

Канал или узел, предоставляющий содержимое

Лента включает описание источника, поэтому сайта, на котором публикуются документы. Его URL, название домашней страницы, описание сайта.

<channel>
    <title></title>
    <link>https://www.iqlevsha.ru/</link>     
    <description></description> 
<channel>

И здесь название тегов зависит от используемого формата.

Элементы, представляющие статьи, размещаются после описания канала, как показано ниже в различных форматах.

Различия в форматах

Глобальная разница между RSS 2.0 и Atom заключается в том, что RSS использует контейнер rss, а atom - только канал. Другие различия связаны с именами тегов.
Что касается RSS 1.0, который основан на RDF, синтаксис заметно отходит от двух других форматов.

Формат RSS 2.0

Пример основан на спецификации гарвардского стандарта RSS 2.0.

<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Xul News</title>
      <link>https://www.iqlevsha.ru/</link>
      <description>Réaliser un lecteur de flux.</description>
      <language>fr-FR</language>
      <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
      <item>
         <title>Tutoriel</title>        
         <link>https://www.iqlevsha.ru/rss/</link>
         <description></description>
         <pubDate>Jeu, 28 Sep 2007 09:39:21 GMT</pubDate>
      </item>
   </channel>
</rss>

Формат RSS 1.0 на основе RDF

Формат 1.0 использует те же имена тегов, что и 2.0, что облегчит создание универсального накопителя. Однако существуют различия в структурах. Во-первых, контейнер rdf принадлежит к одноимённому пространству имен. Структура определяется в теге канала, но описания элементов добавляются после этого тега.

Приведенный ниже пример основан на спецификации стандарта RSS 1.0.

<?xml version="1.0"?>
<rdf:RDF 
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns="http://purl.org/rss/1.0/"
>
 <channel rdf:about="http://www.xml.com/xml/news.rss">
    <title>iqlevsha.ru</title>
    <link>https://www.iqlevsha.ru</link>
    <description>   </description>
    <image rdf:resource="https://www.iqlevsha.ru/images/logo.gif" />
    <items>
        <rdf:Seq>
            <rdf:li resource="https://www.iqlevsha.ru/rss/" />
             ...autres articles...
         </rdf:Seq>
    </items>
  </channel>
  <image rdf:about="https://www.iqlevsha.ru/images/logo.gif">
       <title>iqlevsha.ru</title>
       <link>https://www.iqlevsha.ru</link>
       <url>https://www.iqlevsha.ru/universal/images/logo.gif</url>
 </image>
 <item rdf:about="https://www.iqlevsha.ru/rss/l">
      <title>RSS</title>
      <link>https://www.iqlevsha.ru/rss/</link>
      <description>   </description>
 </item>...autres items...
</rdf:RDF>

Даже если формат более сложный, использование останется простым с XML-функциями PHP и DOM.

Формат Atom, общая структура

Формат Atom использует канал непосредственно в качестве корневого контейнера. Тег канала - feed, а элементы - entry.

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="https://www.iqlevsha.ru">
  <title>Exemple de flux</title> 
  <link href="https://www.iqlevsha.ru/rss/"/>
  <updated></updated>
  <author> 
    <name>Denis Sureau</name>
  </author> 
  <entry>
    <title>Réaliser un lecteur de flux</title>
    <link href="https://www.iqlevsha.ru/rss/lecteur-de-flux.php"/>
    <updated></updated>
    <summary>Une description.</summary>
  </entry>
</feed>

Видно, что Atom использует имена чистых тегов, в то время как оба формата RSS имеют один и тот же формат, что поможет нам определить формат файла потока.

Использование DOM с PHP 5

Шаблон объекта документа позволяет извлекать теги в XML или HTML-документе. Для получения списка тегов, имя которых указано в параметре, будет использоваться функция getElementsByTagName. Эта функция возвращает список в формате DOMNodeList, содержащий элементы в формате DOMNode.
Он применяется к всему документу или элементу DOMNode и, таким образом, позволяет извлечь части файла, канала или элемента и найти в этой части список тегов.

Извлечение RSS-канала
DOMDocument $doc = new DOMDocument("1.0");
DOMNodeList $canal = $doc->getElementsByTagName("channel");

Для потока Atom будет использоваться параметр «feed». Обратите внимание, что имена классов здесь для информирования, PHP-код их не использует.

Извлечение первого элемента
DOMElement $element = $canal.item(0);

Можно назначить DOMNode непосредственно при вызове метода item (), который возвращает DOMNode.
Преимущество в том, что DOMElement имеет атрибуты и методы, которые можно использовать для доступа к содержимому элемента.

Извлечение всех элементов
for($i = 0; $i < $canal->length; i++)
{
    $element = $canal->item(i);
}
Использование данных элемента

Для каждого элемента, как и для канала, компоненты извлекаются одним и тем же методом и с атрибутом firstChild. Например, для названия:

$title = $element.getElementsByTagName("title");   // obtenir la liste des balises title
$title = $title->item(0);  // obtenir la balise
$title = $title->firstChild->textContent;  // obtenir le contenu de la balise

Если не удается извлечь один элемент, используется getElementsByTagName для извлечения списка, который на самом деле будет содержать один элемент, и вместе с методом item извлекается этот элемент.
В XML содержимое тега рассматривается как подэлемент, поэтому для получения XML-элемента содержимого и данных для текстового содержимого используется свойство firstChild.

Тогда остается применить эти методы к каналу и каждому элементу потока, чтобы получить его содержимое.

Для более общего использования проигрывателя потока реализуемая функция возвращает содержимое в двухмерный массив. Затем у нас будет выбор, как его использовать: показать прямо на веб-странице или выполнить обработку на этой таблице.

Как определить формат

Определить формат очень просто, если известно, что RSS 1.0 и 2.0 используют одни и те же тэги, и поэтому одна и та же функция может применяться к этим двум форматам. Это позволит распознать формат Atom в контейнере feed, в то время как RSS 2.0 использует канал, а 1.0 - rdf.
Поскольку в обеих версиях RSS используется тег channel, именно наличие тега feed позволяет идентифицировать этот формат.

DOMDocument $doc = new DOMDocument("1.0");
DOMNodeList $canal = $doc->getElementsByTagName("feed");
$isAtom = ($canal != false);

Пытаются извлечь канал по тегу «feed». Если интерпретатор найдет этот тег, список типа DOMNodeList будет содержать элемент. Флаг isAtom устанавливается на истину, когда объект не пуст, поскольку присутствует тег, иначе поток будет обработан как RSS без различия.

Считывание данных канала

Так что известно, как извлечь канал. Та же функция может использоваться с строками «feed» или «channel» в качестве параметра.
Предполагается, что указатель документа является глобальной переменной, $ doc.

function extractChannel($chan)
{
   DOMNodeList $canal = $doc->getElementsByTagName($chan);
   return $canal->item(0);
}

Затем можно с помощью следующей функции, которая называется именем каждого тега в параметре, прочитать заголовок и каждый описательный элемент канала.

function getTag($tag)
{
   $content = $canal->getElementsByTagName($tag);
   $content = $content->item(0);
   return($content->firstChild->textContent);
}

Затем функция будет называться последовательно с параметром «title», «link», «describition»...

Имена будут зависеть от формата, это будет «сводный» или «тонкий» для Atom и «описательный» для остальных.

Чтение данных элементов

Принцип будет таким же, но нам придется по петле обрабатывать список элементов, пока есть только один канал.

Также следует учитывать, что RSS 1.0 помещает описания элементов вне тега канала, в то время как они содержатся там для других форматов. Элементы содержатся в feed в Atom, в channel в RSS 2.0, но в rdf: RDF в RSS 1.0.

Функция extractItems извлекает список элементов, его переводят в параметр «item» для RSS и «entry» для Atom:

function extractItems($tag)
{
   DOMNodeList $dnl = $doc->getElementsByTagName($tag);
   return $dnl;
}

Возвращенный список используется для доступа к каждому элементу. Он добавляется в таблицу $ a.
Пример с форматом RSS.

$a = array();
$items = extractItems("item");
for($i = 0; $i < $items->length; i++)
{
    array_push($a, $items->item($i));
}

Можно также непосредственно создать массив тегов элемента, title, link, описание для каждого элемента и поместить его в двухмерный массив.
Для этого будет использована ранее определенная родовая версия функции getTag:

function getTag($item, $tag)
{
   $content = $item->getElementsByTagName($tag);
   $content = $content->item(0);
   return($content->firstChild->textContent);
}

for($i = 0; $i < $items->length; i++)
{
    $a = array();
    $item = $items->item($i);
    array_push($a,  getTag($item, "title"));
   ... même chose pour chaque balise d'un élément ...

    array_push($FeedArray, $a);
}

Поэтому мы поместили каждую статью в двухмерную таблицу, которую можно просто показать или использовать по своему усмотрению. Приведенный выше цикл будет помещен в функцию getTags.

Функции полного диска

Теперь у нас есть список всех полезных функций для универсального читателя.

При соответствующих настройках эти функции используются для всех форматов.

Загрузка потока

В самом простом случае поток предназначен для интеграции в веб-страницу либо до загрузки, либо позднее по запросу пользователя.

Независимо от формата, и особенно для потоков на французском языке, необходимо учитывать совместимость формата кодировки, который чаще всего является UTF-8 для потока, а иногда ISO-8159 или windows-1252 для страницы, где будет отображаться поток.
Кодировку UTF-8 лучше дать странице, чтобы избежать неправильного отображения подчеркнутых символов.

Кодировка дана мета типа содержимого со строкой в следующем формате:

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

Загрузка со страницей

При необходимости отображения страницы, содержащей поток, в HTML-код вставляется следующий код:

<?php
include("universal-reader.php");
Universal_Reader("https://www.iqlevsha.ru/rss.xml");
echo Universal_Display();
?>

См. демонстрацию ниже.

Загрузка по требованию

Этот случай возникает, когда посетитель выбирает поток из списка или сам вводит название потока.
После этого загрузка может осуществляться в Ajax для асинхронного отображения или только в PHP, переназначая страницу.
Форма с текстовым полем ввода будет использоваться, чтобы указать URL-адрес потока или простую ссылку (или выбор ссылок), по которой можно щелкнуть для отображения потока.

Загрузка

Загрузить функции Universal Reader в архив Zip.

Она содержит две демонстрации.

Дополнительная информация