getDocNamespaces()
SimpleXML — расширение PHP для работы с XML-документами. Метод SimpleXMLElement::getDocNamespaces() возвращает объявленные пространства имён.
Введение
SimpleXML — это расширение PHP, предоставляющее простой объектно-ориентированный API для чтения XML-документов. Пространства имён XML позволяют двум словарям использовать один документ, не создавая конфликтов имён элементов — каждое пространство имён идентифицируется URI и обычно обозначается коротким префиксом (например, bk в <bk:title>).
SimpleXMLElement::getDocNamespaces() — это метод, который сообщает, какие пространства имён объявлены в документе. Как правило, к нему обращаются перед вызовом children() или xpath() для данных с пространствами имён, поскольку для адресации этих узлов необходимы URI. В этой главе рассматриваются синтаксис, влияние флага $recursive, ловушка с пространством имён по умолчанию и отличие метода от схожего по названию getNamespaces().
Синтаксис
public SimpleXMLElement::getDocNamespaces(bool $recursive = false, bool $from_root = true): array$recursive— когда равенfalse(по умолчанию), возвращаются только пространства имён, объявленные на корневом элементе. Когда равенtrue, сканируется всё дерево документа, и включаются пространства имён, объявленные на любом потомке.$from_root— когда равенtrue(по умолчанию), сканирование начинается с корня документа, даже если метод вызывается на дочернем элементе. Установитеfalse, чтобы сканировать только начиная с текущего узла.
Возвращаемое значение — ассоциативный array, который сопоставляет каждый префикс пространства имён (строку перед двоеточием) с его URI.
Базовый пример
Следующий документ объявляет одно пространство имён, bk, на корневом элементе:
Вывод:
Prefix: bk, URI: https://example.com/booksМетод возвращает ассоциативный array, поэтому цикл foreach с $prefix => $uri обходит все объявления за один проход.
Что на самом деле меняет $recursive
Флаг имеет значение только тогда, когда пространство имён объявлено ниже корня. Здесь lib находится на корне, а dc объявлен на вложенном элементе <details>:
<?php
$xml = new SimpleXMLElement(
'<library xmlns:lib="https://example.com/library">'
. ' <lib:book>'
. ' <details xmlns:dc="https://purl.org/dc/elements/1.1/">'
. ' <dc:title>PHP Basics</dc:title>'
. ' </details>'
. ' </lib:book>'
. '</library>'
);
echo "Root only:\n";
print_r($xml->getDocNamespaces(false));
echo "Whole document:\n";
print_r($xml->getDocNamespaces(true));Вывод:
Root only:
Array
(
[lib] => https://example.com/library
)
Whole document:
Array
(
[lib] => https://example.com/library
[dc] => https://purl.org/dc/elements/1.1/
)Передавайте true, если не можете гарантировать, что все пространства имён объявлены на корне — в фидах и агрегированных документах дополнительные пространства имён нередко объявляются глубже в дереве.
Ловушка с пространством имён по умолчанию
Пространство имён, объявленное с помощью xmlns="..." (без префикса), является пространством имён по умолчанию документа. getDocNamespaces() возвращает его под ключом с пустой строкой, а не под URI:
<?php
$xml = new SimpleXMLElement(
'<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">'
. '<entry><title>Hello</title></entry>'
. '</feed>'
);
print_r($xml->getDocNamespaces(true));Вывод:
Array
(
[] => http://www.w3.org/2005/Atom
[media] => http://search.yahoo.com/mrss/
)Этот URI с пустой строкой понадобится для чтения узлов в пространстве имён по умолчанию, например: $xml->children('http://www.w3.org/2005/Atom'), или путём его регистрации через registerXPathNamespace() перед запросом xpath().
getDocNamespaces() и getNamespaces()
Эти два метода легко перепутать:
| Метод | Область действия |
|---|---|
getDocNamespaces() | Пространства имён, объявленные в документе (атрибуты xmlns), независимо от того, используются ли они. |
getNamespaces() | Пространства имён, фактически используемые элементом и (опционально) его дочерними элементами — объявленные, но неиспользуемые пространства имён исключаются. |
Коротко: getDocNamespaces() отвечает на вопрос «что определяет этот документ?», а getNamespaces() — «что использует эта часть документа?».
Когда применять
- Перед запросом узлов с пространствами имён — передайте возвращённые URI в
children($uri)илиregisterXPathNamespace(). - При обработке стороннего XML (RSS/Atom, SOAP, RSS Media, SVG), где вы не контролируете префиксы.
- Для инспектирования или проверки объявлений пространств имён в незнакомом документе.
Заключение
SimpleXMLElement::getDocNamespaces() возвращает ассоциативный array префиксов пространств имён и URI, объявленных в XML-документе. Используйте значение по умолчанию (false), если все пространства имён находятся на корне, и передавайте true для сканирования всего дерева. Помните, что пространство имён по умолчанию (без префикса) возвращается под ключом с пустой строкой, и обращайтесь к getNamespaces(), когда важно знать, какие пространства имён фактически используются, а не просто объявлены.