W3docs

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, на корневом элементе:

php— editable, runs on the server

Вывод:

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(), когда важно знать, какие пространства имён фактически используются, а не просто объявлены.

Практика

Практика
Что возвращает SimpleXMLElement::getDocNamespaces(true) в отличие от getDocNamespaces() (по умолчанию)?
Что возвращает SimpleXMLElement::getDocNamespaces(true) в отличие от getDocNamespaces() (по умолчанию)?
Was this page helpful?