НОУ ИНТУИТ | Лекция | Взаимодействие 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 -документах могут быть связаны между собой отношениями родитель/потомок или родственник/родственник. В нашем примере <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.
Если вы устанавливаете этот компонент вне приложения 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_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 |
Имя метода | Имя функции | Примечание |
---|---|---|
тэг | ДомЭлемент_тэг() | |
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_value() | |
указанный | DomAttribute_specified() |
Имя метода | Имя функции | Примечание |
---|---|---|
цель | ДомПроцессингИнструкция_цель() | |
данные | ДомПроцессингИнструкция_данные() |
Имя метода | Имя функции | Примечание |
---|---|---|
add_chunk | Parser_add_chunk() | |
конец | Parser_end() |
Имя метода | Имя функции | Примечание |
---|---|---|
оценка | XPathContext_eval() | |
eval_expression | XPathContext_eval_expression() | |
регистр_нс | XPathContext_register_ns() |
Имя метода | Имя функции | Примечание |
---|---|---|
имя | ДомДокументТип_имя() | |
объекты | DomDocumentType_entities() | |
обозначения | ДомДокументТип_нотации () | |
public_id | ТипДокумента_public_id() | |
идентификатор_системы | ДомДокументТип_система_ид() | |
внутреннее_подмножество | ДомДокументТип_internal_subset() |
Классы DomDtd являются производными от DomNode. DomComment является производным от ДомCДата.
Примеры
Для многих примеров в этом справочнике требуется строка XML. Вместо повторяя эту строку в каждом примере, она будет помещена в файл которые будут включены в каждый пример. Этот включаемый файл показан в следующий пример раздела. Кроме того, вы можете создать XML-документ и читай с ДомДокумент_открыть_файл() .
Пример №1 Включить файл example.inc со строкой XML
$xmlstr = "
[
]>
&sp
morerows='1'>b1
?>
известных уязвимостей — Является ли 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.