yakoffka.ru
    грабли, костыли и велосипеды php, css, html, js и прочего

    PHP 2016. Уровень 3.3: PHP + XML

    ошибки phpРабота с xml-документами. конспект-памятка видеокурса 'Программирование на PHP 2016'. Лектор Борисов Игорь Олегович. Учебный Центр «Специалист» при МГТУ им. Н.Э.Баумана.

    конспектировал Капустин Яков

    оглавление

    XML (/ˌeks em ˈel/ англ. eXtensible Markup Language) — расширяемый язык разметки. Рекомендован Консорциумом Всемирной паутины (W3C). Спецификация XML описывает XML-документы и частично описывает поведение XML-процессоров (программ, читающих XML-документы и обеспечивающих доступ к их содержимому). XML разрабатывался как язык с простым формальным синтаксисом, удобный для создания и обработки документов программами и одновременно удобный для чтения и создания документов человеком, с подчёркиванием нацеленности на использование в Интернете.

    XML является подмножеством SGML.

    Язык называется расширяемым, поскольку он не фиксирует разметку, используемую в документах: разработчик волен создать разметку в соответствии с потребностями к конкретной области, будучи ограниченным лишь синтаксическими правилами языка. Расширение XML — это конкретная грамматика, созданная на базе XML и представленная словарём тегов и их атрибутов, а также набором правил, определяющих какие атрибуты и элементы могут входить в состав других элементов. Сочетание простого формального синтаксиса, удобства для человека, расширяемости, а также базирование на кодировках Юникод для представления содержания документов привело к широкому использованию как собственно XML, так и множества производных специализированных языков на базе XML в самых разнообразных программных средствах.

    XML это набор синтаксических правил. Каждый раз, когда мы пишем свой xml-файл, мы фактически создаём свой уникальный язык разметки. Если предположить, что HTML это автомобиль, то XML это станок для производства автомобилей.

    Предназначен для:

    • хранения структурированных данных;
    • обмена информацией между программами;
    • создания на его основе других, более специализированных, языков разметки (OFX, OTP, WSDL, SOAP, VML, XSL, ebXML, CML, XLANG).

    Цель создания: обеспечение совместимости при передаче структурированных данных между разными системами обработки информации.

    Различия XML и HTML:

    • HTML описывает ИЗ ЧЕГО СОСТОИТ и КАК отображать документ;
    • XML определяет ЗНАЧЕНИЕ и ОТНОШЕНИЕ данных.
    • Если документ содержит символы, выходящие за рамки ASCII, необходимо указать кодировку;
    • XML-документ состоит из вложенных элементов;
    • Элемент состоит из открывающего и закрывающего тегов, а также содержимого;
    • XML чувствителен к регистру символов;
    • Элементы могут вкладывться друг в друга;
    • Теги должны быть правильно вложены друг в друга;
    • Все парные теги должны быть закрыты;
    • Возможно формирование пустых элементов;
    • Должен существовать только один корневой элемент, который содержит все остальные элементы. Пустой документ (без корневого элемента) недопустим;
    • Элементы могут иметь атрибуты;
    • Значения атрибутов заключаются в одинарные или двойные кавычки;
    • У каждого конкретного элемента не должно быть повторяющихся атрибутов.

    Создадим пример xml-файла:

    Содержимое файла '_php33/_classes/example_fb.xml':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <?xml version="1.0" encoding="utf-8" ?><!-- пролог (декларация xml) -->
      <catalog><!-- корневой элемент -->

        <book>
          <author>Виктор Олегович Пелевин</author>
          <title>Омон Ра</title>
          <pubYear>1992</pubYear>
          <price>200</price>
          <curr>RUB</curr>
        </book>

        <book>
          <author>Чарльз Майкл (Чак) Палагнюк</author>
          <title>Бойцовский клуб</title>
          <pubYear>1997</pubYear>
          <price>300</price>
          <curr>RUB</curr>
        </book>

        <book>
          <author>Виктор Олегович Пелевин</author>
          <title>Смотритель</title>
          <pubYear>2015</pubYear>
          <price>300</price>
          <curr>RUB</curr>
        </book>

        <book>
          <author>Клим Александрович Жуков</author>
          <title>Почему не надо казнить чучело Солженицына</title>
          <pubYear>2016</pubYear>
          <price>50</price>
          <curr>RUB</curr>
        </book>

        <book>
          <author>Виктор Олегович Пелевин</author>
          <title>Достающее звено. 2 тома</title>
          <pubYear>2017</pubYear>
          <price>600</price>
          <curr>RUB</curr>
        </book>

        <book>
          <author>Виктор Олегович Пелевин</author>
          <title>Тайные виды на гору Фудзи</title>
          <pubYear>2018</pubYear>
          <price>300</price>
          <curr>RUB</curr>
        </book>

      </catalog>
      

    Выведем созданный файл во фрейме для проверки на отсутствие ошибок:

    PHP Code:
    1
    2
    3

      
    echo '<iframe src="https://yakoffka.ru/src/conspects/_php33/_classes/example_fb.xml" width="100%" height="60"></iframe>';
      
    Result:

    Корректными XML-документами (well-formed) являются документы, полностью соответствующие правилам оформления XML. Корректность проверяется XML-парсером. Валидные XML-документы (valid) - корректные XML-документы, которые соответствуют заранее определенному набору правил. Валидность проверяется валидатором.

    Описание структуры документа возможно через DTD – Document Type Definition, либо через XML схемы.

    В курсе php необходимо научиться читать (парсить), изменять и создавать xml. Для этого в php существуют следующие средства работы с xml:

    • SAX (Simple API for XML) - чтение XML-документа;
    • DOM (Document Object Model) - чтение, модификация и создание новых XML-документов;
    • SimpleXML - чтение и модификация XML-документов;
    • XMLReader и XMLWriter - чтение и модификация XML-документов;
    • XSL/T (Extensible Stylesheet Language Transformations) - преобразование XML-документов в другие форматы

    (англ. Простой программный интерфейс для работы с XML, сокращенно SAX ) - спецификация прикладного программного интерфейса для последовательного получения данных из структурированных XML документов. Этот интерфейс является распространенной альтернативой Document Object Model (DOM) но, в отличие от DOM, для SAX нет формальной спецификации.

    Синтаксический анализатор SAX только сообщает о каждом событии синтаксического анализа в том порядке, в котором они происходят, и обычно отбрасывает почти всю эту информацию после сообщения (однако он сохраняет некоторые данные, например, порядок и список всех элементов, которые еще не были закрыты, чтобы потом отлавливать ошибки, такие как незакрытые элементы и неправильный порядок их закрытия)

    Таким образом, минимальный объем памяти, необходимый для синтаксического анализатора SAX, пропорционален максимальной глубине XML-файла (Дерева XML) и объему данных, участвующих в одном событии XML (например, имени и атрибутах текущего элемента). Объём занимаемой памяти обычно считается незначительным по сравнению с парсером DOM, который напротив для начала должен построить древовидное представление всего документа в памяти, используя память таким образом, что она увеличивается по мере чтения документа (это занимает значительное время). Преимущество DOM заключается в том, что после загрузки любая часть документа может быть доступна в любом порядке.

    Анализатор, реализующий интерфейс SAX (англ. SAX Parser ) обрабатывает информацию из XML документа как единый поток данных. Этот поток данных, как было указано выше, доступен только в одном направлении, то есть, раньше обработанные данные невозможно повторно прочитать без повторного анализа. Парсеры SAX работают с каждым фрагментом XML-документа последовательно, генерируя события синтаксического анализа.

    SAX анализаторы реализуют с использованием подхода передачи сообщений (event-driven), когда программисту необходимо описать обработчики событий (en: Callback (computer science)), которые вызываются анализаторами при обработке XML документа.

    SAX был разработан усилиями сообщества без формальных комитетов, но он был быстро признан компаниями, специализирующимися на средствах обработки XML документов. Первым главным разработчиком и инженером сопровождения был Давид Маггинсон.

    Simple API for XML (SAX) не читает файлы - на вход создаваемому парсеру должна подаваться xml-строка. Нет проверки на валидность.

    • Официальный сайт Simple API for XML;
    • Описывает метод парсинга XML-документов для получения данных из них;
    • Создавать и изменять XML-документы с помощью SAX невозможно;
    • Основан на событиях;
    • XML-парсеру предоставляется набор собственных функций для обработки различных типов XML-данных;
    • Парсер автоматически вызывает эти функции в процессе последовательной обработки XML-документа.

    Использование SAX:

    Использование SAX:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

      
    // Создание парсера:
      
    $sax xml_parser_create("utf-8");

      
    // Декларация функций обработки событий:
      
    function onStart($parser,$tag,$attributes){}
      function 
    onEnd($parser$tag){}
      function 
    onText($parser$text){}

      
    // Регистрация функций как обработчиков событий:
      
    xml_set_element_handler($sax,"onStart","onEnd");
      
    xml_set_character_data_handler($sax,"onText");

      
    // Запуск парсера:
      
    xml_parse($sax"XML строка!");

      
    // Обработка ошибок:
      
    echo xml_error_string(xml_get_error_code($sax));
      

    Для примера выведем созданный выше файл '_php33/_classes/example_fb.xml' в виде таблицы с помощью SAX:

    Пример использования Simple API for XML для парсинга xml-файлов:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95

      
    // // Создание парсера:
      // $sax_parser=xml_parser_create("utf-8");
      //
      //
      // // Функция обработчик открывающих тегов
      // function opening_tag($parser,$tag,$attr){
      //   // по умолчанию $tag приводит имя элемента к верхнему регистру!!!
      //   if($tag=="CATALOG"){echo "<table class='blue_table'><caption>Каталог книг</caption><tr><th>№</th><th>автор</th><th>название</th><th>год</th><th>цена</th><th>валюта</th></tr>";
      //   }elseif($tag=="BOOK"){
      //     static $i_static=0;
      //     $i_static++;
      //     echo "<tr><td>$i_static</td>";
      //   }else{echo "<td>";}
      // }
      //
      // // Функция обработчик закрывающих тегов
      // function closing_tag($parser,$tag){
      //   if($tag=="CATALOG"){echo "</table>";
      //   }elseif($tag=="BOOK"){echo "</tr>";
      //   }else{echo "</td>";}
      // }
      //
      // // Функция обработчик содержимого элементов
      // function on_text($parser,$text){echo "$text";}
      //
      //
      // // Привязка событий
      // // Назначение обработчиков открывающих и закрывающих тегов
      // xml_set_element_handler($sax_parser,"opening_tag","closing_tag");
      //
      // // Назначение обработчика содержимого элементов
      // xml_set_character_data_handler($sax_parser,"on_text");
      //
      // // Запуск парсера
      // xml_parse($sax_parser,file_get_contents("/full/path/to/_php33/_classes/example_fb.xml"));
      //
      // // Обработка ошибок
      // // echo xml_error_string(xml_get_error_code($sax_parser));
      // $err=xml_error_string(xml_get_error_code($sax_parser));
      // if($err!="No error"){echo $err;}




      // парсинг в переменную с помощью суперглобального массива $GLOBALS
      
    $GLOBALS["res"]="";

      
    // Создание парсера
      
    $sax_parser=xml_parser_create("utf-8");


      
    // Функция обработчик открывающих тегов
      
    function opening_tag($parser,$tag,$attr){
        
    // по умолчанию $tag приводит имя элемента к верхнему регистру!!!
        
    if($tag=="CATALOG"){$GLOBALS["res"].="<table class='blue_table'><caption>Каталог книг</caption><tr><th>№</th><th>автор</th><th>название</th><th>год</th><th>цена</th><th>валюта</th></tr>";
        }elseif(
    $tag=="BOOK"){
          static 
    $i_static=0;
          
    $i_static++;
          
    $GLOBALS["res"].="<tr><td>$i_static</td>";
        }else{
    $GLOBALS["res"].="<td>";}
      }

      
    // Функция обработчик закрывающих тегов
      
    function closing_tag($parser,$tag){
        if(
    $tag=="CATALOG"){$GLOBALS["res"].="</table>";
        }elseif(
    $tag=="BOOK"){$GLOBALS["res"].="</tr>";
        }else{
    $GLOBALS["res"].="</td>";}
      }

      
    // Функция обработчик содержимого элементов
      
    function on_text($parser,$text){
        
    $GLOBALS["res"].="$text";
      }


      
    // Привязка событий
      // Назначение обработчиков открывающих и закрывающих тегов
      
    xml_set_element_handler($sax_parser,"opening_tag","closing_tag");

      
    // Назначение обработчика содержимого элементов
      
    xml_set_character_data_handler($sax_parser,"on_text");

      
    // Запуск парсера
      
    xml_parse($sax_parser,file_get_contents("/full/path/to/_php33/_classes/example_fb.xml"));

      
    // Обработка ошибок
      // echo xml_error_string(xml_get_error_code($sax_parser));
      
    $err=xml_error_string(xml_get_error_code($sax_parser));
      if(
    $err!="No error"){$GLOBALS["res"].= $err;}


      
    // Вывод результата
      
    echo $GLOBALS["res"];
      
    Result:
    Каталог книг
    авторназваниегодценавалюта
    1 Виктор Олегович Пелевин Омон Ра 1992 200 RUB
    2 Чарльз Майкл (Чак) Палагнюк Бойцовский клуб 1997 300 RUB
    3 Виктор Олегович Пелевин Смотритель 2015 300 RUB
    4 Клим Александрович Жуков Почему не надо казнить чучело Солженицына 2016 50 RUB
    5 Виктор Олегович Пелевин Достающее звено. 2 тома 2017 600 RUB
    6 Виктор Олегович Пелевин Тайные виды на гору Фудзи 2018 300 RUB

    (от англ. Document Object Model — «объектная модель документа») — это независящий от платформы и языка программный интерфейс, позволяющий программам и скриптам получить доступ к содержимому HTML-, XHTML- и XML-документов, а также изменять содержимое, структуру и оформление таких документов.

    Модель DOM не накладывает ограничений на структуру документа. Любой документ известной структуры с помощью DOM может быть представлен в виде дерева узлов, каждый узел которого представляет собой элемент, атрибут, текстовый, графический или любой другой объект. Узлы связаны между собой отношениями «родительский-дочерний».

    Изначально различные браузеры имели собственные модели документов (DOM), несовместимые с остальными. Для обеспечения взаимной и обратной совместимости специалисты международного консорциума W3C классифицировали эту модель по уровням, для каждого из которых была создана своя спецификация. Все эти спецификации объединены в общую группу, носящую название «W3C DOM».

    История DOM переплетается с историей «браузерных войн» в конце 1990-х годов между Netscape Navigator и Microsoft Internet Explorer (и между первыми скриптовыми языками JavaScript и JScript) за то, чтобы широко использоваться в механизме вёрстки веб-страниц.

    Язык программирования «JavaScript» был выпущен фирмой «Netscape Communications» в 1995 году в рамках веб-браузера «Netscape Navigator 2.0». Конкурент фирмы «Netscape» — фирма «Microsoft» выпустила позже в том же году веб-браузер «Internet Explorer 3.0» с портом JavaScript, названным «JScript». JavaScript и JScript позволяют разработчикам создавать веб-страницы, которые были бы интерактивны со стороны клиента. Ограниченные возможности обнаружения создаваемых пользователем событий и изменения документа HTML в первом поколении этих языков в итоге стали известны как «DOM уровня 0» или «традиционный DOM». Для DOM уровня 0 не было разработано никакого независимого стандарта, однако он был частично описан в спецификации HTML4.

    Всё узел. Куда ни плюнь - везде узел. И сам документ тоже узел.

    Некоторые типы узлов документа
    Название интерфейсаКод типаОписание
    ELEMENT1Узел элемента. Любой элемент на странице
    ATTR2Узел атрибута (возвращает набор атрибутов элемента XML- или HTML-документа)
    TEXT3Текстовый узел
    COMMENT8Узел комментария
    DOCUMENT9Объект Document. Узел документа (основа доступа к содержанию документа и создания его составляющих)
    DOCUMENTTYPE10Узел декларации типа документа (возвращает тип данного документа)
    DOCUMENTFRAGMENT11Несколько узлов, объединенных в один фрагмент (используется при создании и добавлении узлов в документ)

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

    Использование DOM:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58

      
    // 1 Чтение XML-документа
      // Создание объекта, экземпляра класса DomDocument
      
    $dom = new DomDocument();

      
    // Загрузка документа
      
    $dom->load("catalog.xml");

      
    // Получение коневого элемента
      
    $root $dom->documentElement;

      
    // Получение типа узла
      
    echo $root->nodeType// 1

      // Получение коллекции дочерних узлов (экземпляр класса DomNodeList)
      
    $children $root->childNodes;

      
    // Получение текстового содержимого узла
      
    $content $root->textContent;

      
    // Получение коллекции элементов с определённым именем
      
    $books $dom->getElementsByTagName("book");


      
    // 2 Создание/изменение XML-документа
      // Создание объекта, экземпляра класса DomDocument
      
    $dom = new DomDocument("1.0""utf-8");

      
    // Получение коневого элемента
      
    $root $dom->documentElement;

      
    // Создание новых элементов
      
    $book $dom->createElement("book");
      
    $title $dom->createElement("title");

      
    // Создание текстового узла
      
    $text $dom->createTextNode("Название книги");

      
    // Добавление узлов к узлам
      
    $title->appendChild($text);
      
    $book->appendChild($title);
      
    $root->appendChild($book);

      
    // Другой вариант создания нового элемента
      
    $author $dom->createElement("author""Автор книги");

      
    // Добавляем узел к узлу перед другим узлом ($author перед $title)
      
    $book->insertBefore($author$title);

      
    // Создаём секцию CDATA
      
    $description $dom->createElement("description");
      
    $cdata $dom->createCDATASection("...описание книги...");
      
    $description->appendChild($cdata);
      
    $book->appendChild($description);

      
    // Сохраняем документ
      
    $dom->save("catalog.xml");
      

    Если при парсинге в SAX применялся процедурный стиль, то в DOM используется ООП.

    Выведем файл '_php33/_classes/example_fb.xml' в виде таблицы с помощью DOM:

    Пример использования Document Object Model для парсинга xml-файлов:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

      
    // очистка содержимого переменной $res
      
    $GLOBALS["res"]="";

      
    // Создание объекта, экземпляра класса DomDocument
      
    $dom = new DomDocument();

      
    // Загрузка документа
      
    $dom->load("/full/path/to/_php33/_classes/example_fb.xml");

      
    // Получение коневого элемента
      
    $root $dom->documentElement;

      
    // Получение коллекции дочерних узлов (экземпляр класса DomNodeList)
      
    $books $root->childNodes;
      
    // var_dump($books); // object(DOMNodeList)#1 (1) { ["length"]=> int(14) }
      // Получение доступа к вложенным в узел "BOOK" узлам через foreach()
      
    $key=0;
      foreach(
    $books as $book){
        
    // Проверка на тип полученного ребёнка. в $book будут также и текстовые узлы - переводы строк
        // если дочерний узел является элементом (здесь - book)
        
    if($book->nodeType==1){
          
    $key++;
          
    $GLOBALS["res"].="<tr><td>$key</td>";
          
    // $GLOBALS["res"].=gettype($book);  // object
          
    foreach($book->childNodes as $childBook){
            
    // если дочерний узел опять таки является элементом (здесь - author, title..)
            
    if($childBook->nodeType==1){
              
    $GLOBALS["res"].="<td>$childBook->textContent</td>";
            }
          }
          
    $GLOBALS["res"].="</tr>";
        }
      }

      
    $GLOBALS["res"]="<table class='blue_table'><caption>Каталог книг</caption><tr><th>№</th><th>автор</th><th>название</th><th>год</th><th>цена</th><th>валюта</th></tr>".$GLOBALS["res"]."</table>";


      
    // Вывод результата
      
    echo $GLOBALS["res"];

      
    Result:
    Каталог книг
    авторназваниегодценавалюта
    1Виктор Олегович ПелевинОмон Ра1992200RUB
    2Чарльз Майкл (Чак) ПалагнюкБойцовский клуб1997300RUB
    3Виктор Олегович ПелевинСмотритель2015300RUB
    4Клим Александрович ЖуковПочему не надо казнить чучело Солженицына201650RUB
    5Виктор Олегович ПелевинДостающее звено. 2 тома2017600RUB
    6Виктор Олегович ПелевинТайные виды на гору Фудзи2018300RUB

    Любой(?) парсер продолжает разбирать текстовый узел на предмет наличия в нём вложенных элементов (тип PCDATA - Parsed Character Data. Это не просто текст, а текст, который нужно распарсить) и неизбежно упадёт при встрече с html-сущностями. Парсер xml даже не подозревает о их существовании.

    Для запрета дальнейшего парсинга и предотвращения падений парсера пользуют секцию CDATA - character data, символьные данные. CDATA показывает, что определённая часть документа представляет собой символьные данные, в отличие от несимвольных или символьных, но особым образом структурированных данных.

    В XML документах фрагмент, помещённый внутрь CDATA, — это часть содержания элемента, которая помечена для парсера как содержащая только символьные данные, а не разметку. CDATA — это просто альтернативный синтаксис для отображения символьных данных, нет никакой смысловой разницы между символьными данными, которые объявлены как CDATA и символьными данными, которые объявлены в обычном синтаксисе и где '<' и '>' будут представлены как '&lt;' и '&gt;', соответственно.

    Раздел CDATA начинается со следующей последовательности символов '<![CDATA[' и заканчивается с первым появлением последовательности ']]>'. Все символы, заключённые между этими двумя последовательностями, интерпретируются как символы, а не как разметка или ссылки на объект.

    Новички в использовании XML часто неверно представляют назначение раздела CDATA, как «защиту» от обработки данных внутри этого раздела наряду с обычными символьными данными. Некоторые API для работы с XML документами предоставляют независимый доступ к разделу CDATA, но эти возможности существуют поверх и вне обычных требований к системе обработки XML и не меняют смысл этих данных. Символьные данные — это символьные данные, независимо от того, записаны они в раздел CDATA или же с помощью обычной разметки.

    Раздел CDATA полезен, когда надо написать XML код как текстовые данные внутри XML документа. Например, если надо набрать книгу про XML на XSL с примерами использования XML приложений, то встречающиеся примеры будут заключены в CDATA. Однако, CDATA не может содержать строку ']]>' и, следовательно, невозможно создавать вложенные разделы CDATA. Если текст содержит ']]>', то можно его отобразить, используя, например, несколько разделов CDATA, оканчивая один из них перед символом '>': '<![CDATA[]]]]><![CDATA[>]]>'

    Упражнение 1: Знакомство со структурой RSS-документа
    • В текстовом редакторе откройте файл news/rss.txt и ознакомьтесь со структурой RSS-документа
    • В текстовом редакторе откройте файл news/NewsDB.class.php
    • Добавьте константу класса RSS_NAME для хранения имени RSS-файла, например, rss.xml
    • Добавьте константу класса RSS_TITLE для хранения заголовка новостной ленты, например, Последние новости
    • Добавьте константу класса RSS_LINK для хранения ссылки на саму новостную ленту - https://yakoffka.ru/news
    Упражнение 2: Создание метода для формирования RSS-документа
    • Создайте и опишите метод createRss(), который будет формировать RSS-документ
    • Создайте объект $dom, экземпляр класса DOMDocument
    • Напишите следующие строки для правильного форматирования документа:
      '$dom->formatOutput = true;'
      '$dom->preserveWhiteSpace = false;'
    • Создайте корневой элемент rss и привяжите его к объекту $dom
    • Напишите следующие строки для создания атрибута version корневого элемента:
      '$version = $dom->createAttribute('version');'
      '$version->value = '2.0';'
      '$rss->appendChild($version);'
    • Создайте элемент channel и привяжите его к корневому элементу
    • Создайте элементы title и link, и привяжите их к элементу channel. Содержимое элементов находится в константах RSS_TITLE и RSS_LINK
    • Получите данные в виде массива из базы данных и дальнейшие действия производите в цикле
    • Cоздайте новый XML-элемент item для очередной новости
    • Cоздайте XML-элементы для всех данных новостной ленты (вместе с текстовыми узлами): title, link, description, pubDate, category. Не забудьте обернуть текст для элемента description секцией CDATA
    • Привяжите созданные XML-элементы с данными к XML-элементу item
    • Привяжите XML-элемент item к элементу channel
    • Сохраните файл. Имя файла - константа RSS_NAME
    • Вызовите метод createRss() после добавления новости в методе saveNews()
    • Сохраните файл news/NewsDB.class.php
    Упражнение 3: Создание RSS-документа
    • Запустите браузер
    • Наберите в адресной строке браузера http://mysite.local/news/news.php
    • Добавьте запись в новостную ленту
    • Убедитесь, что в папке news появился файл rss.xml
    • Откройте файл news/rss.xml и убедитесь, что данные записаны корректно
    • Попробуйте добавить еще несколько записей в новостную ленту

    Просмотрим содержимое файла news/rss.txt

    ознакомление со структурой RSS-документа: файл news/rss.txt:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="utf-8"?>
      <rss version="2.0">
        <channel>
          <title>Заголовок новостной ленты</title>
          <link>Ссылка на новостную ленту (абсолютный URL)</link>
          <item>
            <title>Заголовок новости</title>
            <link>Ссылка на новость (абсолютный URL)</link>
            <description>Содержание новости</description>
            <pubDate>Дата публикации новости</pubDate>
            <category>Категория новости</category>
          </item>
        </channel>
        <channel>
          <title>Заголовок новостной ленты</title>
          <link>Ссылка на новостную ленту (абсолютный URL)</link>
          <item>
            <title>Заголовок новости</title>
            <link>Ссылка на новость (абсолютный URL)</link>
            <description>Содержание новости</description>
            <pubDate>Дата публикации новости</pubDate>
            <category>Категория новости</category>
          </item>
        </channel>
      </rss>
      

    Ввиду того, что необходимо интегрировать лабораторную работу в структуру сайта, мы пойдём немного другим путём, отличным от рекомендованного выше.

    Для начала скопируем файлы новостной ленты, не требующие изменения (в итоге этими файлами оказались лишь файлы классов), из директории '_php32' в текущую директорию '_php33'.

    копирование файлов новостной ленты, не требующих изменения:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

      $res
    ="";

      
    $arr_cf=array(
        
    "/_classes/INewsDB.class.php",
        
    "/_classes/NewsDB.class.php",
      );

      
    // проверка существования директории "/full/path/to/_php33_classes/"
      
    $pd="/full/path/to/_php33/_classes";
      if(!
    is_dir($pd)){if(!mkdir($pd,0777,true)){$res.="Не удалось создать директорию $pd.<br>\n";}}

      foreach(
    $arr_cf as $nf){
        
    $source="/full/path/to/_php32$nf";
        
    $dest="/full/path/to/_php33$nf";
        if(
    is_file($source)){
          if(
    copy($source,$dest)){
            
    $res.="Файл $nf скопирован успешно.<br>\n";
          }else{
    $res.="Не удалось скопировать файл $nf.<br>\n";}
        }else{
    $res.="Файл $nf не найден.<br>\n";}
      }

      echo 
    $res;
      
    Result:
    Файл /_classes/INewsDB.class.php скопирован успешно.
    Файл /_classes/NewsDB.class.php скопирован успешно.

    Теперь создадим класс NewsDB_RSS - наследник NewsDB, в котором опишем требуемые константы и метод createRss().

    Содержимое файла '_php33/_classes/NewsDB_RSS.class.php':
    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    012
    013
    014
    015
    016
    017
    018
    019
    020
    021
    022
    023
    024
    025
    026
    027
    028
    029
    030
    031
    032
    033
    034
    035
    036
    037
    038
    039
    040
    041
    042
    043
    044
    045
    046
    047
    048
    049
    050
    051
    052
    053
    054
    055
    056
    057
    058
    059
    060
    061
    062
    063
    064
    065
    066
    067
    068
    069
    070
    071
    072
    073
    074
    075
    076
    077
    078
    079
    080
    081
    082
    083
    084
    085
    086
    087
    088
    089
    090
    091
    092
    093
    094
    095
    096
    097
    098
    099
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    <?php
      
    class NewsDB_RSS extends NewsDB// наследуем класс NewsDB
        //--------------------------------------------------------------------------
        // Добавление констант класса
        //--------------------------------------------------------------------------
        // Добавление константы класса RSS_NAME для хранения имени RSS-файла
        
    const RSS_NAME "/full/path/to/_php33/rss.xml";
        
    // Добавление константы класса RSS_TITLE для хранения заголовка новостной ленты
        
    const RSS_TITLE "Последние новости";
        
    // Добавление константы класса RSS_LINK для хранения ссылки на саму новостную ленту
        
    const RSS_LINK "https://yakoffka.ru/news";


        
    //--------------------------------------------------------------------------
        // описание метода createRss()
        //--------------------------------------------------------------------------
        
    private function createRss(){  // приватим метод по совету Игорь Олегыча
          // Создание объекта $dom, экземпляра класса DOMDocument
          
    $dom=new DOMDocument("1.0""utf-8");

          
    // правильное (читабельное) форматирование документа
          // formatOutput Форматирует вывод, добавляя отступы и дополнительные пробелы
          
    $dom->formatOutput true;
          
    // preserveWhiteSpace false - Указание убирать лишние пробелы и отступы. По умолчанию TRUE
          
    $dom->preserveWhiteSpace false;

          
    // создание корневого элемента
          
    $rss $dom->createElement("rss");
          
    // Добавление узла $rss к узлу $dom
          
    $dom->appendChild($rss);

          
    // создание атрибута version корневого элемента
          
    $version $dom->createAttribute("version");
          
    $version->value "2.0";
          
    $rss->appendChild($version);

          
    // создание элемента channel и привязка его к корневому элементу rss
          
    $channel $dom->createElement("channel");
          
    // Добавление узла channel к узлу rss
          
    $rss->appendChild($channel);

          
    // создание элементов title и link и привязка их к элементу channel
          
    $title $dom->createElement("title"self::RSS_TITLE);
          
    $link $dom->createElement("link"self::RSS_LINK);
          
    // Добавление узлов title и link к узлу channel
          
    $channel->appendChild($title);
          
    $channel->appendChild($link);


          
    // получение данных в виде массива из db
          // $arrNews=$this->getNews();
          
    if(!$arrNews=$this->getNews()){return false;}

          foreach(
    $arrNews as $news){

            
    // создание нового XML-элемента item для добавляемой новости
            
    $item $dom->createElement("item");

            
    // создание XML-элементов для данных новостной ленты вместе с текстовыми узлами
            
    $title $dom->createElement("title");
            
    $titleText $dom->createTextNode($news["title"]);
            
    $title->appendChild($titleText);

            
    $category $dom->createElement("category");
            
    $categoryText $dom->createTextNode($news["category"]);
            
    $category->appendChild($categoryText);

            
    $description $dom->createElement("description");
            
    $descriptionCDATASection $dom->createCDATASection($news["description"]);  // !!!
            
    $description->appendChild($descriptionCDATASection);

            
    $source $dom->createElement("source");
            
    $sourceText $dom->createTextNode($news["source"]);
            
    $source->appendChild($sourceText);

            
    $pubDate $dom->createElement("pubDate");
            
    $pubDateText $dom->createTextNode(date("Y.m.d",$news["datetime"]));
            
    $pubDate->appendChild($pubDateText);


            
    $link $dom->createElement("link");
            
    $linkText $dom->createTextNode("https://yakoffka.ru/conspects/laboratory_3.3.1/".$news["id"]);
            
    $link->appendChild($linkText);


            
    // привязка XML-элементов к элементу item
            
    $item->appendChild($title);
            
    $item->appendChild($category);
            
    $item->appendChild($description);
            
    $item->appendChild($source);
            
    $item->appendChild($pubDate);
            
    $item->appendChild($link);


            
    // привязка XML-элемента item к элементу channel !!!не описано!!!
            
    $channel->appendChild($item);
          }

          
    // сохранение XML-документа
          
    if($dom->save(self::RSS_NAME)){
            return 
    true;
          }else{return 
    false;}

        }


        
    //--------------------------------------------------------------------------
        // добавление метода для выдачи определённой новости по её id
        //--------------------------------------------------------------------------
        // ПЕРЕПИСАТЬ!!!
        
    function getIDNews($id){
          
    $sql="SELECT msgs.id as id,
              title,
              category.name as category,
              description,
              source,
              datetime
            FROM msgs, category
            WHERE category.id = msgs.category
            ORDER BY msgs.id DESC"
    ;
          
    $res $this->_db->query($sql);
          if(
    $res){
            return 
    $this->db2arr($res);
          }else{
            return 
    false;
          }
        }


        
    //--------------------------------------------------------------------------
        // переопределение методов класса для обновления ленты при добавлении либо удалении новости
        //--------------------------------------------------------------------------
        // переопределение метода saveNews()
        
    function saveNews($title,$category,$description,$source){
          if(
    parent::saveNews($title,$category,$description,$source)){  // выполнение перегруженного родительского метода
            
    return $this->createRss();
          }else{
            return 
    false;
          }
        }

        
    // переопределение метода deleteNews()
        
    function deleteNews($id){
          if(
    parent::deleteNews($id)){  // выполнение перегруженного родительского метода
            
    return $this->createRss();
          }else{
            return 
    false;
          }
        }


      }
      

    Перепишем файл '_classes/save_rss_news.inc.php', изменив в нём Location.

    Содержимое файла '_php33/_classes/save_rss_news.inc.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
      $t
    =$news->clearStr($_POST["title"]);
      
    $c=$news->clearStr($_POST["category"]);
      
    $d=$news->clearStr($_POST["description"]);
      
    $s=$news->clearStr($_POST["source"]);

      if(empty(
    $t) or empty($d)){
        
    $errMsg.="Заполните все поля!<br>\n";
      }else{
        if(!
    $news->saveNews($t,$c,$d,$s)){
          
    $errMsg.="Произошла ошибка при добавлении новости в db.<br>\n";
        
    // вызов метода теперь производится в описании методов saveNews() и deleteNews()
        // }elseif(!$news->createRss()){
        //   $errMsg.="Произошла ошибка при добавлении новости в rss.<br>\n";
        
    }else{
          
    header("Location: https://yakoffka.ru/conspects/laboratory_3.3.1");// избавляемся от $_POST
          
    exit;
        }
      }

      

    Перепишем файл '_php33/_classes/get_news.inc.php', в котором изменим form action и осуществим вывод краткого описания новости.

    Содержимое файла '_php33/_classes/get_news.inc.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <?php
      $result
    =$news->getNews();
      if(!
    is_array($result)){
        
    $errMsg.='Ошибка вывода ленты новостей.<br>\n';
        
    $result->columnType(0);
        
    $result->columnType(1);
        
    $result->columnType(2);
        
    $result->columnType(3);

      }else{
        echo 
    '<p>новостей: '.count($result).'шт.</p>';

        foreach(
    $result as $key=>$arr_news){
          
    // получение краткого описания новости
          
    $short_description=substr($arr_news['description'],0,strrpos(substr($arr_news['description'],0,300)," "))." <a href='https://yakoffka.ru/conspects/laboratory_3.3.1/".$arr_news['id']."'>...читать</a>";
          echo 
    "
            <div class='news'>
              <h2>"
    .$arr_news['title']."</h2>
              <!--div class='id'>id="
    .$arr_news['id']."</div-->
              <div class='datetime'>"
    .date('Y.m.d',$arr_news['datetime'])." ".$arr_news['category']."</div>
              <!--div class='description'>"
    .$arr_news['description']."</div-->
              <div class='short_description'>
    $short_description</div>
              <div class='source'>источник: "
    .$arr_news['source']."</div>
              <br>
              <form action='https://yakoffka.ru/conspects/laboratory_3.3.1' method='post'>
                <input type='hidden' name='del_news' value='"
    .$arr_news['id']."'>
                <input type='submit' value='удалить эту новость'></p>
              </form>
            </div>
          "
    ;
        }
      }
      

    Создадим файл '_php33/_classes/get_id_news.inc.php', отвечающий за выдачу определённой статьи.

    Содержимое файла '_php33/_classes/get_id_news.inc.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php
      $id
    =$_GET['get_id_news'];
      
    $result=$news->getIDNews($id);
      if(!
    is_array($result)){
        
    $errMsg.='Ошибка вывода ленты новостей.<br>\n';

      }else{
        foreach(
    $result as $key=>$arr_news){
          if(
    $arr_news['id']==$_GET['get_id_news']){
            
    // разделение текста на абзацы по переносам строк
            
    $description="<p>".preg_replace("~[\n]{1,}~u","</p><p>",$arr_news['description'])."</p>";
            
    $from_inc.="
              <div class='news'>
                <h2>"
    .$arr_news['title']."</h2>
                <!--div class='id'>id="
    .$arr_news['id']."</div-->
                <div class='datetime'>"
    .date('Y.m.d',$arr_news['datetime'])." ".$arr_news['category']."</div>
                <div class='description'>
    $description</div>
                <div class='source'>источник: "
    .$arr_news['source']."</div>
              </div>
              <a href='https://yakoffka.ru/conspects/laboratory_3.3.1'>«к редактированию новостей»</a>
              <a href='https://yakoffka.ru/conspects/laboratory_3.3.2'>«к ленте новостей»</a>
            "
    ;
          }
        }
      }
      

    Изменим Location и в файле '_php33/_classes/delete_news.inc.php'.

    Содержимое файла '_php33/_classes/delete_news.inc.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    <?php
      $id
    =$news->clearInt($_POST['del_news']);
      if(
    $id>0){
        if(!
    $news->deleteNews($id)){
          
    $errMsg.="Ошибка удаления записи.<br>\n";
        }else{
          
    header("Location: https://yakoffka.ru/conspects/laboratory_3.3.1");// избавляемся от $_POST
          
    exit;
        }
      }
      

    Создаём основной файл новостной ленты с rss - видоизменённый файл новостной ленты. Также добавим правило RewriteRule в .htaccess для вновь создаваемого файла.

    Содержимое файла 'laboratory_3.3.1.php' '/full/path/to/laboratory_3.3.1.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53

      
    // реализуем метод автозагрузки
      
    spl_autoload_register(function($class){
        include(
    DIR_SRC_CONSP_PHP33."/_classes/$class.class.php");
      });

      
    $errMsg="";
      
    $from_inc="";
      
    $showAll=true;

      
    $news=new NewsDB_RSS();

      if(
    $_SERVER['REQUEST_METHOD']=='POST'){
        if(
    $_POST['title']){
          require 
    DIR_SRC_CONSP_PHP33."/_classes/save_rss_news.inc.php";
        }elseif(
    $_POST['del_news']){
          require 
    DIR_SRC_CONSP_PHP33."/_classes/delete_news.inc.php";
        }
      }elseif(
    $_SERVER['REQUEST_METHOD']=='GET'){
        if(
    $_GET['get_id_news']){
          require 
    DIR_SRC_CONSP_PHP33."/_classes/get_id_news.inc.php";
          
    $showAll=false;
        }
      }
      
        
    $mc.="
          <p class='err_mess'><?php echo \$errMsg;?></p>

          <?php
            echo \$from_inc;
            if(\$showAll){
              echo \"
                Примечание: По умолчанию выводится страница с формой добавления новостей и списком новостей, уже существующих в базе.
                <h2>Добавление новости</h2>
                <form action='https://yakoffka.ru/conspects/laboratory_3.3.1' method='post'>
                  <p>Заголовок новости: <input type='text' name='title' style='width:200px;'>
                  Выберите категорию:
                  <select name='category'>
                    <option value='1'>Наука</option>
                    <option value='2'>Образование</option>
                    <option value='3'>Культура</option>
                  </select>
                  Текст новости:</p>
                  <textarea name='description' cols='90' rows='10' style='width:100%'></textarea><br>
                  <p>Источник: <input type='text' name='source'> <input type='submit' value='Добавить'></p>
                </form>
              \";

              require('/full/path/to/_php33/_classes/get_news.inc.php');
            }
          ?>
        "
    ;
      

    Результат выполнения работы: laboratory_3.3.1.

    Расширение SimpleXML предоставляет очень простой и легкий в использовании набор инструментов для преобразования XML в объект, с которым можно затем работать через его свойства и с помощью итераторов.

    В PHP получить доступ к элементу в XML документе, содержащим в названии недопустимые символы (например, дефис), можно путем заключения данного имени элемента в фигурные скобки и апострофы.

    Доступ к неуникальным элементам в SimpleXML. Если в одном родительском элементе существует несколько экземпляров дочерних элементов, то нужно применять стандартные методы итерации, например, foreach. Свойства не являются массивами. Это итерируемые объекты в виде массива.

    Для сравнения элемента или атрибута со строкой или для передачи в функцию в качестве текста, необходимо привести его к строке, используя (string). В противном случае, PHP будет рассматривать элемент как объект.

    Два элемента SimpleXMLElements считаются разными, даже если они указывают на один и тот же объект, начиная с PHP 5.2.0.

    SimpleXML включает в себя встроенную поддержку XPath. Рекомендован к использованию.

    Использование SimpleXML:

    Использование SimpleXML:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

      
    // загрузка документа и преобразование его в объект
      
    $sxml=simplexml_load_file("name_file.xml");
      
    // Используйте функцию libxml_use_internal_errors() для того,
      // чтобы подавить все ошибки XML,
      // и функцию libxml_get_errors() для прохода по ним впоследствии.

      // загрузка xml-строки и преобразование её в объект
      
    $sxml=simplexml_load_string("string");

      
    // получение текста нужного элемента
      
    echo $sxml->book[1]->title;

      
    // получение атрибута элемента
      // Получить доступ к атрибуту элемента можно так же, как к элементам массива
      
    echo $sxml->book[1]->title["lang"];

      
    // добавление дочерних элементов
      
    $character->addChild("name""Mr. Parser");

      
    // добавление атрибута элемента
      
    $rating->addAttribute("type""mpaa");

      
    // изменение текста нужного элемента
      
    $sxml->book[1]->title="новое название";

      
    // преобразование объекта в строку
      
    $str_xml=$sxml->asXML();

      
    // запись строки в файл
      
    file_put_contents("name_file.xml",$sxml);
      

    PHP может преобразовывать XML-узлы из SimpleXML в формат DOM и наоборот. Этот пример показывает, как можно изменить DOM-элемент в SimpleXML.

    Взаимодействие SimpleXML с DOM:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12

      $dom 
    = new DOMDocument;
      
    $dom->loadXML("<books><book><title>чепуха</title></book></books>");
      if (!
    $dom) {
        echo 
    "Ошибка при разборе документа";
        exit;
      }

      
    $books simplexml_import_dom($dom);

      echo 
    $books->book[0]->title;
      
    Result:
    чепуха

    Выведем файл '_php33/_classes/example_fb.xml' в виде таблицы с помощью SimpleXML, предварительно добавив туда книгу и исправим вкравшуюся ошибку, изменив автора уже находящейся в нём книги:

    Взаимодействие SimpleXML с DOM:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

      $GLOBALS
    ["res"]="";

      
    // интерпретируем XML-файл в объект класса SimpleXMLElement со свойствами, содержащими данные,
      // которые хранятся внутри (корневого документа?) XML-документа
      // (см. http://php.net/manual/ru/function.simplexml-load-file.php)
      
    $catalog=simplexml_load_file("/full/path/to/_php33/_classes/example_fb.xml");

      
    // добавляем ещё одну книгу
      
    $book=$catalog->addChild("book");
      
    $book->addChild("author","Станислав Владимирович Дробышевский");
      
    $book->addChild("title","Шанс для приматов");
      
    $book->addChild("pubYear","2016");
      
    $book->addChild("price","150");
      
    $book->addChild("curr","RUB");

      
    $GLOBALS["res"].="<table class='blue_table'><caption>Каталог книг</caption><tr><th>№</th><th>автор</th><th>название</th><th>год</th><th>цена</th><th>валюта</th></tr>";
      
    $i=0;
      foreach(
    $catalog as $book){
        
    //при нахождении книги с нужным названием меняем автора
        
    if($book->title=="Достающее звено. 2 тома"){
          
    $book->author="Станислав Владимирович Дробышевский";
        }

        
    $i++;
        
    $GLOBALS["res"].=
          
    "<tr><td>".$i.
          
    "</td><td>".$book->author.
          
    "</td><td>".$book->title.
          
    "</td><td>".$book->pubYear.
          
    "</td><td>".$book->price.
          
    "</td><td>".$book->curr.
          
    "</td></tr>";
      }
      
    $GLOBALS["res"].="</table>";


      
    // Вывод результата
      
    echo $GLOBALS["res"];

      
    // Запись объекта в файл
      
    file_put_contents("/full/path/to/_php33/_classes/example_fb_copy.xml",$catalog->asXML());
      
    file_put_contents("/full/path/to/_php33/_classes/example_fb_copy.txt",$catalog->asXML());

      
    Result:
    Каталог книг
    авторназваниегодценавалюта
    1Виктор Олегович ПелевинОмон Ра1992200RUB
    2Чарльз Майкл (Чак) ПалагнюкБойцовский клуб1997300RUB
    3Виктор Олегович ПелевинСмотритель2015300RUB
    4Клим Александрович ЖуковПочему не надо казнить чучело Солженицына201650RUB
    5Станислав Владимирович ДробышевскийДостающее звено. 2 тома2017600RUB
    6Виктор Олегович ПелевинТайные виды на гору Фудзи2018300RUB
    7Станислав Владимирович ДробышевскийШанс для приматов2016150RUB

    Выведем исправленный файл во фрейме для проверки:

    PHP Code:
    1
    2
    3
    4

      
    echo '<iframe src="https://yakoffka.ru/src/conspects/_php33/_classes/example_fb_copy.xml" width="100%" height="70"></iframe>';
      echo 
    '<iframe src="https://yakoffka.ru/src/conspects/_php33/_classes/example_fb_copy.txt" width="100%" height="200"></iframe>';
      
    Result:
    • В текстовом редакторе откройте файл news/rss_reader.php
    • Пересохраните этот файл как C:\Users\Public\OpenServer\domains\localhost ss_reader.php
    • Создайте константу RSS_URL для хранения адреса RSS-потока со значением http://mysite.local/news/rss.xml
    • Создайте константу FILE_NAME для хранения RSS-документа на локальном сервере со значением news.xml
    • Обычно новости обновляются с какой-либо периодичностью. Поэтому нет необходимости каждую минуту (и даже секунду) дёргать файл с удалённого сервера. Лучше закешировать данные у себя на локальном сервере и обновлять их через определённый период. Для этого создайте и опишите кеширующую функцию download(), которая закачивает RSS-документ с адреса RSS_URL и сохраняет его на локальном сервере под именем FILE_NAME
    • Проверьте, существует ли файл на на локальном сервере? Если НЕТ, то создайте его с помощью функции download()
    • После заголовка первого уровня Последние новости зачитайте с помощью SimpleXML RSS-документ:
      • Создайте объект - экземпляр класса SimpleXML и загрузите документ;
      • В цикле выведите в произвольной форме новостную ленту.
    • Осуществите проверку на необходимость загрузки свежего RSS-файла на локальный сервер с помощью функции download()
    • Сохраните файл rss_reader.php

    Выведем файл rss.txt' (копию rss.xml' для сохранения структуры) во фрейме для наглядности:

    PHP Code:
    1
    2
    3
    4

      copy
    ("/full/path/to/_php33/rss.xml","/full/path/to/_php33/rss.txt");
      echo 
    '<iframe src="https://yakoffka.ru/src/conspects/_php33/rss.txt" width="100%" height="200"></iframe>';
      
    Result:

    создание файла rss_reader.php:

    Содержимое файла 'laboratory_3.3.2.php' '/full/path/to/laboratory_3.3.2.php':
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

      
    // создание констант
      
    const RSS_URL="https://yakoffka.ru/src/conspects/_php33/rss.xml";  // и так сойдёт
      
    const FILE_NAME="/full/path/to/_php33/rss_local.xml";  // адрес RSS-документа на локальном сервере
      
    const RSS_TTL=3600;  // периодичность в секундах

      
    $errMsg="";

      function 
    download($url,$fp){
        
    $str=file_get_contents($url);
        if(
    $str){
          if(
    file_put_contents($fp,$str)){$errMsg="лента новостей обновлена";
          }else{
    $errMsg="не удалось создать файл 'FILE_NAME'.";}
        }else{
    $errMsg="не удалось получить файл 'RSS_URL'.";}
        return 
    $errMsg;
      }

      if(!
    is_file(FILE_NAME) OR time()>filemtime(FILE_NAME)+RSS_TTL){
        
    $errMsg.=download(RSS_URL,FILE_NAME);
      }


      
    // парсим в переменную с помощью суперглобального массива $GLOBALS
      
    $GLOBALS["res"]="";

      
    // Создание парсера:
      
    $simplexml=simplexml_load_file(FILE_NAME);

      
    $GLOBALS["res"].=$channel->title;

      foreach(
    $simplexml->channel->item as $item){
        
    $GLOBALS["res"].="
          <div class='lab_item'>
            <h3 class='left'><span class='timestamp_writing'>
    {$item->pubDate} {$item->category}</span> <a class='no_decoration' href='{$item->link}'>«{$item->title}»</a></h3>
          </div>
        "
    ;
      }
      
        
    $mc.="
          <p class='err_mess'><?php echo \$errMsg;?></p>
          <h2>Просмотр ленты новостей</h2>

          <?php
            // Вывод результата
            echo \$GLOBALS['res'];
          ?>
        "
    ;
      

    XSL/T (от англ. Extensible Stylesheet Language /Transformations) - Стилевая технология, предназначенная для трансформации XML-документов в другие форматы. Ничего общего с CSS.

    Таблицы стилей XSL создаются по правилам XML-документов. Таблицы стилей XSL состоят из набора шаблонов.

    XLT-процессоры на основании xml-документа и шаблонов, в которых указаны правила преобразования узлов, формируют, например, html-документ.

    Все современные браузеры имеют встроенные xsl-процессоры, то есть преобразование идёт на клиентской стороне. Но можно выполнить преобразование и на стороне сервера.

    .

    Использование xsl на стороне сервера:

    Использование xsl на стороне сервера:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17

      
    // Загрузка исходного XML-документа
      
    $xml = new DomDocument();
      
    $xml->load ('catalog.xml');

      
    // Загрузка таблицы стилей XSL
      
    $xsl = new DomDocument();
      
    $xsl -> load ('catalog.xsl');

      
    // Создание XSLT-процессора и загрузка в него
      
    таблицы стилей
      $processor 
    = new XSLTProcessor();
      
    $processor -> importStylesheet($xsl);

      
    // Выполнение преобразования
      
    echo $processor -> transformToXML($xml);