Этот вопрос предназначен как ссылка на ответ на особенно распространенный вопрос, который может иметь разные формы:
Если ваш вопрос был закрыт как дубликат этого, он может не совпадать с этими примерами, но эта страница должна рассказать вам, что вам нужно знать.
Вот пример:
$xml = ' <?xml version="1.0" encoding="utf-8"?> <document xmlns="http://example.com" xmlns:ns2="https://namespaces.example.org/two" xmlns:seq="urn:example:sequences"> <list type="short"> <ns2:item seq:position="1">A thing</ns2:item> <ns2:item seq:position="2">Another thing</ns2:item> </list> </document> '; $sx = simplexml_load_string($xml);
Этот код не будет работать ; почему нет?
foreach ( $sx->list->ns2:item as $item ) { echo 'Position: ' . $item['seq:position'] . "\n"; echo 'Item: ' . (string)$item . "\n"; }
Первая проблема заключается в том, что ->ns2:item
является недопустимым синтаксисом; но изменение его на это тоже не работает :
foreach ( $sx->list->{'ns2:item'} as $item ) { ... }
Почему нет, и что вы должны использовать вместо этого?
Двоеточие (:) в имени тега или атрибута означает, что элемент или атрибут находится в пространстве имен XML . Пространства имен – это способ комбинирования разных форматов / стандартов XML в одном документе и отслеживание имен имен из какого формата. Двоеточие и часть, находящаяся перед ним, на самом деле не являются частью имени тега / атрибута, они просто указывают, в каком пространстве имён оно находится.
Пространство имен XML имеет идентификатор пространства имен , который идентифицируется URI (URL или URN). URI не указывает ни на что, это просто способ, чтобы кто-то «владел» пространством имен. Например, стандарт SOAP использует пространство имен http://www.w3.org/2003/05/soap-envelope
а файл OpenDocument использует (среди прочих) urn:oasis:names:tc:opendocument:xmlns:meta:1.0
, В примере в вопросе используются пространства имен http://example.com
и https://namespaces.example.org/two
.
В документе или разделе документа пространству имен присваивается локальный префикс , который является частью, которую вы видите перед двоеточием. Например, в разных документах пространству имен SOAP может быть предоставлено локальное префиксное soap:
SOAP:
SOAP-ENV:
env:
или просто ns1:
Эти имена связаны с идентификатором пространства имен с помощью специального атрибута xmlns
, например xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
. Выбор префикса в конкретном документе полностью произволен и может меняться каждый раз, когда он был сгенерирован без изменения значения.
Наконец, в каждом документе или разделе документа есть пространство имен по умолчанию , которое является пространством имен, используемым для элементов без префикса. Он определяется атрибутом xmlns
без :
например xmlns="http://www.w3.org/2003/05/soap-envelope"
. В приведенном выше примере <list>
находится в пространстве имен по умолчанию, которое определяется как http://example.com
.
В некоторой степени уникальные атрибуты без префикса никогда не входят в пространство имен по умолчанию, а в виде «пространства имен void», которое стандарт четко не определяет. См.: Пространства имен XML и атрибуты Unprefixed
SimpleXML предоставляет два основных метода использования пространств имен:
->children()
позволяет вам обращаться к дочерним элементам в определенном пространстве имен. Он эффективно переключает ваш объект на это пространство имен, пока вы не вызовете его снова, чтобы переключиться обратно или в другое пространство имен. ->attributes()
работает аналогичным образом, но позволяет вам обращаться к атрибутам в определенном пространстве имен. Оба этих метода принимают идентификатор пространства имен в качестве первого аргумента. Поскольку эти идентификаторы довольно длинные, может быть полезно определить константу или переменную для представления пространств имен, с которыми вы работаете, поэтому вам не нужно копировать и вставлять полный URI всюду.
Например, приведенный выше пример может стать:
define('XMLNS_EG2', 'https://namespaces.example.org/two'); define('XMLNS_SEQ', 'urn:example:sequences'); foreach ( $sx->list->children(XMLNS_EG2)->item as $item ) { echo 'Position: ' . $item->attributes(XMLNS_SEQ)->position . "\n"; echo 'Item: ' . (string)$item . "\n"; }
В качестве короткой руки вы также можете передать методам локальный псевдоним пространства имен, указав второй параметр как true
. Помните, что этот префикс может измениться в любое время, например, генератор может назначать префиксы ns1
, ns2
и т. Д. И назначать их в другом порядке, если код немного меняется. Используя эту короткую руку, код будет выглядеть следующим образом:
foreach ( $sx->list->children('ns2', true)->item as $item ) { echo 'Position: ' . $item->attributes('seq', true)->position . "\n"; echo 'Item: ' . (string)$item . "\n"; }
(Эта короткая ссылка была добавлена в PHP 5.2, и вы можете увидеть действительно старые примеры, используя более длинную версию с использованием $sx->getNamespaces
чтобы получить список пар префикс-идентификатор.)