НОУ ИНТУИТ | Лекция | Взаимодействие PHP и XML

< Лекция 13 || Лекция 14: 12345 || Лекция 15 >

Аннотация: Лекция знакомит с понятием объектной модели XML-документа и ее использованием в PHP. Установка расширения DOM XML. Обработка элементов XML документа с помощью функций PHP (получение значения узла, атрибута и т.п.) Пример – использование XML-базы данных в качестве альтернативы реляционной СУБД (реализация административного интерфейса каталога виртуального музея).

Ключевые слова: PHP, XML(Extensible Markup Language), синтаксис, DOM XML(Document Object Model), установка расширения dom xml, файл, Личность, элемент, SGML, XML как технология хранения и транспортировки документа, XSLT, закрывающий тег, DTD (Document Type Definition, XML Schemas, структура XML-документа, отношение родитель/потомок, объектная модель XML-докукмента, DOM (Document Object Model), парсер, PHP-скрипт, SAX (Simple API for XML), событийное программирование, файл настроек, php.ini, переменная extension_dir, функция phpinfo(), функция domxml_version(), модуль, DomNode, DomDocument, DomElement, DomText, DomAttribute, класс, адрес, информация, domxml_open_mem, domxml_open_file, корневой элемент, DomDocument->document_element, domxml_new_doc, DomNode->node_value, DomNode->get_content, DomElement->get_attribute, DomNode->child_nodes, XML_ELEMENT_NODE, XML_ATTRIBUTE_NODE, XML_TEXT_NODE, удобочитаемость, DomNode->clone_node, DomNode->append_child, удаление узла, DomNode->unlink_node, PHP5, знание

Введение

intuit.ru/2010/edi»>Прежде чем начать изучать способы работы PHP с XML, полезно хотя бы вкратце ознакомиться с самой технологией XML. В первой части лекции будут рассмотрены основные понятия этой технологии, базовый синтаксис XML–документов, области ее применения, а также понятие DOM XML. Вторая часть лекции посвящена непосредственно вопросам обработки XML при помощи PHP. Сюда входит установка расширения DOM XML, описание и примеры использования некоторых встроенных в PHP функций для обработки XML-документов.

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

XML

Основные понятия

XML (Extensible Markup Language) – это расширяемый язык разметки, являющийся подмножеством языка SGML и поэтому имеющий общие с ним цели – разметка любого типа документов.

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

Для отображения данных, хранящихся в XML -формате, используются различного рода преобразователи, например язык трансформаций XSLT. Комбинация XML + преобразователь позволяет достичь того же результата, что и использование HTML-форматированного отображения документа пользователю. Однако в случае использования XML и преобразователя данные хранятся отдельно от их представления, т. е. от инструкций о том, как они должны отображаться.

XML очень похож на HTML по своему синтаксису, за исключением того, что теги XML можно придумывать собственные. По аналогии с HTML внутри XML -тегов можно использовать атрибуты. Каждый тег XML должен иметь соответствующий закрывающий тег (в HTML это не является обязательным). Каждый XML-документ начинается со строки декларации, например:

<?xml version='1.0' encoding='UTF-16' standalone='yes' ?>

которая указывает на версию языка XML (атрибут version), кодировку текста в этом документе (атрибут encoding ) и показывает, существует ли документ сам по себе или зависит от других файлов (атрибут standalone ).

Приведем пример XML-документа.

Пусть у нас имеется письмо. Содержащуюся в нем информацию можно хранить в следующем виде:

<?xml version='1.0' encoding='KOI8-R'
                    standalone='yes' ?>
<note title="Письмо">
    <to>Маша Петрова</to>
    <body>Привет, Маша! 
    Как у тебя дела? 
    У меня все хорошо.
Собираюсь приехать к тебе в гости.</body> <from>Вася Иванов</from> </note>

Сохранив этот файл, например, как note.xml, мы можем переслать его кому-нибудь, просмотреть с помощью браузера или использовать в программе. В частности, можно использовать этот XML-документ в своей PHP-программе.

С помощью XML можно создать документ для описания любой информации. Для того чтобы другие разработчики могли создавать документы в этом же XML -языке (т.е. используя те же теги) и чтобы можно было проверить правильность созданного документа (его соответствие выбранному XML -языку), нужно формально описать используемый XML -язык. Это делается с помощью механизмов DTD (Document Type Definition) или Schemas, которые дают возможность создавать шаблоны для новых типов документов. Для экспериментов в домашних условиях создавать DTD -описания необязательно. Важно понимать, что XML на самом деле вовсе не язык, а стандарт для создания языков, отвечающих критериям XML.

Между XML-документами могут быть установлены ссылки, один документ может включать в себя другой, т.е. структура документа может быть сколь угодно сложной.

Элементы в XML -документах могут быть связаны между собой отношениями родитель/потомок или родственник/родственник. В нашем примере <note> является родителем <to>, который в свою очередь является потомком <note>, а <to>, <body> и <from> являются родственниками. Собственно текст тоже является потомком элемента, например, » Вася Иванов » – потомок элемента <from>. Такая структура называется деревом; любые части дерева, имеющие потомков, называются ветвями, а не имеющие – листьями.

Дальше >>

< Лекция 13 || Лекция 14: 12345 || Лекция 15 >

Компонент DomCrawler | Symfony

Дата обновления перевода 2023-01-20

Компонент DomCrawler облегчает DOM навигацию для документов HTML и XML.

Note

Несмотря на то, что это возможно, компонент DomCrawler не был создан для управления DOM или повторного сброса HTML/XML.

Note

Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно подключить файл vendor/autoload.php в вашем коде для включения механизма автозагрузки классов, предоставляемых Composer. Детальнее читайте в этой статье.

See also

Эта статья объясняет как использовать функции DomCrawler как независимого компонента в любом приложении PHP. Прочитайте статью Функциональные тесты Symfony для понимания как использовать его при создании тестов Symfony.

Класс Crawler предоставляет методы для запроса и обработки HTML и XML документов.

Экземпляр Crawler представляет собой набор объектов DOMElement, которые по сути являются узлами, которые вы можете с лёгкостью траверсировать.

:

Специальные классы Link, Image и Form полезны для взаимодействия с html ссылками, изображениями и формами во время траверсирования через дерево HTML.

Note

DomCrawler попробует автоматически исправить ваш HTML, чтобы он совпадал с официальной спецификацией. Например, если вы вложите тег <p> в другой тег <p>, он будет перемещён, чтобы быть сестрой родительского тега. Это ожидаемо и является частью спецификации HTML5. И хотя DomCrawler не предназначен для сброса содержания,вы можете увидеть «исправленную» версию вашего HTML, сбросив её .

Note

Если вам нужна лучшая поддержка для содержания HTML5 или вы хотите избавиться от неточностей расширения PHP DOM, установите библиотеку html5-php. Компонент DomCrawler будет использовать его автоматически, если контент будет иметь тип документа HTML5.

Использование выражений XPath очень просто:

Tip

DOMXPath::query используется внутренне, чтобы выполнять запрос XPath.

Если вы предпочитаете CSS-селекторы, а не XPath, установите Компонент CssSelector. Он позволит вам использовать селекторы, схожие с jQuery:

Для фильтрации с более сложными критериями, может быть использвана анонимная функция:

Чтобы удалить узел, анонимная функция должна вернуть «false».

Note

Все методы фильтрации возвращают новый экземпляр Crawler с отфильтрованным содержанием. Чтобы проверить, действительно ли фильтр что-то нашел, используйте $crawler->count() > 0

в этом новом краулере.

Оба метода filterXPath() и filter() работают с пространствами имён XML, которые могут быть либо обнаружены автоматически, либо ясно зарегистрированы.

Рассмотрите XML ниже:

Это может быть отфильтровано с помощью Crawler без необходимости регистрировать дополнительные именя просранства имён как с filterXPath():

так и с filter():

Note

Пространство имён по умолчанию зарегистрировано с префиксом «default». Оно может быть изменено методом setDefaultNamespacePrefix().

Пространство имён по умолчанию удаляется при загрузке содержимого, если оно является единственым пространством имён в нём. Это делается для упрощения запросов xpath.

Пространства имён могут быть ясно зарегистрированы с методом registerNamespace():

Проверьте, соответствует ли текущий узел селектору:

Получите доступ к узлу поего позиции в списке:

Получите первый или последний узел текущего выбора:

Получите узлы того же уровня, что и текущий выбор:

Получите узлы одного уровня до или после текущего выбора:

Получите все родительские или дочерные узлы:

Получите все прямые дочерние узлы, соответствующие CSS-селектору:

Получите первого родителя (в направлении к корню документа) элемента, соответствующего данному селектору:

Note

Все траверсионные методы возвращают новый экзепмпляр Crawler.

Доступ к имени узла (имени HTML тега) первого узла текущего выбора (например, «p» или «div»):

Доступ к значению первого узла текущего выбора:

Доступ к значению атрибута первого узла текущего выбора:

Извлечь значения атрибута и / или узлов из списка узлов:

Note

Специальный атрибут _text представляет значение узла, в то время как _name — название элемента (имя тега HTML).

Вызвать анонимную функцию в каждом узле списка:

Анонимная функция получает узел (как Crawler) и позицию аргументов. Результатом является массив значений, возвращённых анонимными функциональными вызовами.

При использовании вложенного краулера, имейте в виду, что filterXPath() оценивается в контексте краулера:

Сrawler поддерживает несколько способов добавления содержания, но они взаимоисключающие, поэтому вы можете использовать только один из них (например, если вы передаете содержание конструктору Crawler, вы не можете вызвать addContent() позже):::

Note

Методы addHtmlContent() и addXmlContent() по умолчанию имеют кодировку UTF-8, но вы можете изменить это поведение их вторым необязательным аргументом.

Метод addContent() предполагает лучшую кодировку в соответствии с данным содержанием, и по умолчанию является ISO-8859-1, в случае, если невозможно предположить кодировку.

Так как реализация Crawler основывается на расширении DOM, то он также способен взаимодействовать с оригинальными объектами DOMDocument, DOMNodeList и DOMNode:

Метод evaluate() оценивает заданное выражение XPath. Возвратное значение зависит от выражения XPath. Если выражение по оценке является скалярным (например, атрибутами HTML), то будет возвращён массив результатов. Если выражение по оценке является документом DOM, то будет возвращён новый экземпляр Crawler.

Это поведение лучше всего проиллюстрировать с помощью примеров:

Используйте метод filter(), чтобы найти ссылки по их атрибутам id или class, и используйте метод selectLink(), чтобы найти ссылки по их содержанию (также так вы можете найти активные изображения, имеющие это содержание в своем атрибуте alt).

Оба метода возвращают экземпляр Crawler с одной выбранной ссылкой. Используйте метод link(), чтобы получить объект Link, представляющий ссылку:

Объект Link имеет несколько полезных методов, чтобы получить больше информации о самой выбранной ссылке:

Note

getUri() особенно полезен, так как очищает значение href и преобразует его в то, как оно действительно должно быть обработано. Например, для ссылки с href="#foo", будет возвращён полный URI текущей страницы, с суффиксом #foo. Возврат из getUri() — всегда полный URI, с которым вы можете работать.

Чтобы найти изображения по его атрибуту alt, используйте метод selectImage в существующем crawler. Это вернёт экземпляр Crawler только с выбранным(и) изображением(ями). Вызов image() даёт вам специальный объект Image:

Объект Image имеет тот же метод getUri(), что и Link.

Особое внимание уделяется также и формам. Метод selectButton() доступен в Crawler, и возвращает другой Crawler, который совпадает с кнопкой (input[type=submit], input[type=image], или button) с заданным текстом. Этот метод особенно полезен, так как вы можете использовать его, чтобы вернуть объект a Form, который представляет форму, в которой живёт кнопка:

Объект Form имеет множество очень полезных методов для работы с формами:

Метод getUri() делает больше, чем просто возвращает атрибут формы action. Если метод формы — GET, то он имитирует поведение браузера и возвращает атрибут action, за которым следует строка запроса всех значений формы.

Note

Поддерживаются необязательные атрибуты кнопки formaction и formmethod. Методы getUri() и getMethod() принимают во внимание эти атрибуты, чтобы всегда возвращать правильные действие и метод, в зависимости от кнопки, использованной для получения формы.

Вы можете виртуально установить и получить значения формы:

Для работы с многомерными полями:

Передать массив значений:

Это всё прекрасно, но дальше — лучше! Объект Form позволяет вам взаимодействовать с вашей формой, как браузером, выбирая значения радиокнопок, отмечая чекбоксы, и загружая файлы:

В чём смысл этого всего? Если вы тестируете внутренне, то вы можете получать информацию из формы, как будто бы она только была отправлена, используя PHP значения:

Если вы используете внешний HTTP-клиент, то вы можете использовать форму, чтобы получить всю необходимую вам информацию для создания запроса POST для формы:

Прекрасный пример интегрированной системы, который использует это все — HttpBrowser, предоставляемый компонент BrowserKit. Он понимает объект Symfony Crawler и может использовать его для отправки форм напрямую:

По умолчанию, поля выбора (селект, радио) имеют внутренню валидацию, которая активируется, чтобы уберечь вас от установки недопустимых значений. Если вы хотите иметь возможность устанавливать недопустимые значения, вы можете использовать метод disableValidation() либо во всей форме, либо в отдельном(ых) поле(ях):

Класс UriResolver берет URI (относительный, абсолютный, фрагментарный и т.д.) и преращает его в абсолютный URI в соотношении с другим данным базовым URI:

  • Тестирование
  • Компонент CssSelector

Функции DOM XML (PHP 4)

Устаревшие функции

Есть довольно много функций, которые не вписываются в стандарт DOM и больше не следует использовать. Эти функции перечислены в следующей таблице. Функция DomNode_append_child() изменила свою поведение. Теперь он добавляет ребенка, а не родного брата. Если это ломает ваше приложение, используйте не-DOM функцию DomNode_append_sibling().

Устаревшие функции и их замена
Старая функция Новая функция
xmldoc domxml_open_mem()
xmldocfile domxml_open_file()
domxml_new_xmldoc domxml_new_doc()
domxml_dump_mem ДомДокумент_dump_mem()
domxml_dump_mem_file ДомДокумент_dump_file()
DomDocument_dump_mem_file ДомДокумент_dump_file()
DomDocument_add_root DomDocument_create_element() с последующим DomNode_append_child()
ДомДокумент_дтд DomDocument_doctype()
DomDocument_root ДомДокумент_документ_элемент()
ДомДокумент_дети DomNode_child_nodes()
DomDocument_imported_node Нет замены.
DomNode_add_child Создайте новый узел, например. DomDocument_create_element() и добавьте его с помощью DomNode_append_child().
ДомУзел_дети DomNode_child_nodes()
DomNode_parent DomNode_parent_node()
DomNode_new_child Создайте новый узел, например. DomDocument_create_element() и добавьте его с помощью DomNode_append_child().
DomNode_set_content Создайте новый узел, например. DomDocument_create_text_node() и добавьте его с помощью DomNode_append_child().
DomNode_get_content Содержимое — это просто текстовый узел, доступ к которому можно получить с помощью DomNode_child_nodes().
DomNode_set_content Содержимое — это просто текстовый узел, который можно добавить с помощью DomNode_append_child().

Классы

API модуля максимально соответствует стандарту DOM Level 2. насколько это возможно. Следовательно, API полностью объектно-ориентирован. Рекомендуется иметь стандарт DOM доступным, когда используя этот модуль. Хотя API является объектно-ориентированным, существует множество функций, которые могут вызываться не объектно-ориентированным способом, передавая объект для работы в качестве первого аргумента. Эти функции в основном предназначены для сохранения совместимости к более старым версиям расширения и не должны использоваться при создании новых скрипты.

Этот API отличается от официального API DOM двумя способами. Во-первых, все атрибуты класса реализованы как функции с тем же именем. Во-вторых, имена функций соответствуют соглашению об именах PHP. Это означает что функция DOM lastChild() будет записана как last_child().

Этот модуль определяет ряд классов, которые перечислены — включая их метод — в следующих таблицах. Классы с эквивалентом в Стандарт DOM называется DOMxxx.

Список классов
Имя класса Родительские классы
ДомАтрибут ДомУзел
ДомКданные ДомУзел
ДомКомментарий DomCData : DomNode
ДомДокумент ДомУзел
ДомДокументТип ДомУзел
ДомЭлемент ДомУзел
ДомЭнтити ДомУзел
DomEntityReference ДомУзел
ДомПроцессингИнструкция ДомУзел
ДомТекст DomCData : DomNode
Парсер В настоящее время все еще называется DomParser
XPathContext  
Класс DomDocument (DomDocument: DomNode)
Имя метода Имя функции Примечание
тип документа DomDocument_doctype()  
документ_элемент ДомДокумент_документ_элемент()  
create_element ДомДокумент_создать_элемент ()  
create_text_node ДомДокумент_создать_текст_узел ()  
создать_комментарий ДомДокумент_создать_комментарий ()  
create_cdata_section ДомДокумент_создать_cdata_section ()  
create_processing_instruction DomDocument_create_processing_instruction()  
create_attribute ДомДокумент_создать_атрибут()  
create_entity_reference DomDocument_create_entity_reference()  
get_elements_by_tagname ДомДокумент_get_elements_by_tagname()  
get_element_by_id ДомДокумент_get_element_by_id()  
дамп_памяти ДомДокумент_dump_mem() не соответствует стандарту DOM
файл_дампа ДомДокумент_dump_file() не соответствует стандарту DOM
html_dump_mem ДомДокумент_html_dump_mem() не соответствует стандарту DOM
xpath_init xpath_init не соответствует стандарту DOM
xpath_new_context xpath_new_context не соответствует стандарту DOM
xptr_new_context xptr_new_context не соответствует стандарту DOM
Класс DomElement (DomElement : DomNode)
Имя метода Имя функции Примечание
тэг ДомЭлемент_тэг()  
get_attribute ДомЭлемент_get_attribute()  
set_attribute ДомЭлемент_set_attribute()  
удалить_атрибут ДомЭлемент_удалить_атрибут()  
get_attribute_node ДомЭлемент_get_attribute_node()  
set_attribute_node ДомЭлемент_set_attribute_node()  
get_elements_by_tagname ДомЭлемент_get_elements_by_tagname()  
имеет_атрибут ДомЭлемент_has_attribute()  
Класс ДомУзел
Имя метода Примечание
DomNode_node_name()  
DomNode_node_value()  
DomNode_node_type()  
DomNode_last_child()  
DomNode_first_child()  
DomNode_child_nodes()  
DomNode_previous_sibling()  
DomNode_next_sibling()  
DomNode_parent_node()  
DomNode_owner_document()  
DomNode_insert_before()  
DomNode_append_child()  
DomNode_append_sibling() Не соответствует стандарту DOM. Эта функция эмулирует предыдущую поведение DomNode_append_child().
DomNode_remove_child()  
DomNode_has_child_nodes()  
DomNode_has_attributes()  
DomNode_clone_node()  
DomNode_attributes()  
DomNode_unlink_node() Не соответствует стандарту DOM
DomNode_replace_node() Не соответствует стандарту DOM
DomNode_set_content() Не соответствует стандарту DOM, устарело
DomNode_get_content() Не соответствует стандарту DOM, устарело
DomNode_dump_node() Не соответствует стандарту DOM
DomNode_is_blank_node() Не соответствует стандарту DOM
Класс DomAttribute (DomAttribute: DomNode)
Имя метода   Примечание
имя ДомАтрибут_имя()  
значение DomAttribute_value()  
указанный DomAttribute_specified()  
Класс DomProcessingInstruction (DomProcessingInstruction: DomNode)
Имя метода Имя функции Примечание
цель ДомПроцессингИнструкция_цель()  
данные ДомПроцессингИнструкция_данные()  
Класс анализатора
Имя метода Имя функции Примечание
add_chunk Parser_add_chunk()  
конец Parser_end()  
Класс XPathContext
Имя метода Имя функции Примечание
оценка XPathContext_eval()  
eval_expression XPathContext_eval_expression()  
регистр_нс XPathContext_register_ns()  
Класс DomDocumentType (DomDocumentType: DomNode)
Имя метода Имя функции Примечание
имя ДомДокументТип_имя()  
объекты DomDocumentType_entities()  
обозначения ДомДокументТип_нотации ()  
public_id ТипДокумента_public_id()  
идентификатор_системы ДомДокументТип_система_ид()  
внутреннее_подмножество ДомДокументТип_internal_subset()  

Классы DomDtd являются производными от DomNode. DomComment является производным от ДомCДата.

Примеры

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

Пример №1 Включить файл example.inc со строкой XML

$xmlstr = "

]>

Заголовок
 
  &sp
  
  
   
    
     a1< запись
morerows='1'>b1c1

a2c2
a3b3c3
    
   
  
 
";
?>

известных уязвимостей — Является ли php DOMDocument::loadXML полностью безопасным?

спросил

Изменено 8 лет, 8 месяцев назад

Просмотрено 2к раз

Наше приложение широко использует loadXML для получения данных (ввода) от пользователей. Помимо обычных проверок на наличие SQL-инъекций и XXS, существуют ли какие-либо известные риски при синтаксическом анализе файла xml с помощью loadXML? Файлы XML ограничены по размеру и не превышают 2 МБ.

Может ли кто-то потенциально создать файлы XML с вредоносным макросом?

https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)

Я прочитал эти ссылки, но не уверен, можно ли безопасно полагаться на loadXML или нет? Если нет, то какие методы мы должны использовать для очистки или проверки XML как безопасного?

  • php
  • известные уязвимости
  • загрузка файлов
  • проверка
  • xml

5

для XXE прочитайте:

  • http://www.ubercomp.com/posts/2014-01-16_facebook_remote_code_execution
  • http://blog.h4xstream.com/2014/06/identifying-xml-external-entity.