SimpleXml с проблемами пространства имен - PullRequest
0 голосов
/ 04 июня 2018

Я перепробовал почти все, но я не могу прочитать элемент пространства имен "m: inline" и потомков "feed" и "title" из следующего дампа SimpleXMLElement:

SimpleXMLElement {#235
+"@attributes": array:4 [
    "rel" => "http://schemas.microsoft.com/ado/2007/08/dataservices/related/test"
    "type" => "application/atom+xml;type=feed"
    "title" => "some title"
    "href" => "JobRequisition(23453453L)/Test"
]
+"m:inline": SimpleXMLElement {#152
  +"feed": SimpleXMLElement {#123
    +"title": "jobReqLocale"

...some more data ahead skipped here

Необработанный xmlначало:

<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/jobReqLocale" type="application/atom+xml;type=feed" title="some title" href="JobRequisition(23453453L)/Test">
        <m:inline>
            <feed>
                <title type="text">jobReqLocale</title>

...

Я пробовал:

$simpleXmlElement = new SimpleXMLElement($xml, LIBXML_NOERROR, false);

dd($simpleXmlElement->children('m', true)->feed);

Результатом всегда является пустой SimpleXmlElement

со всеми видами вариаций, включая xpath.Я делаю что-то неправильно?Разве SimpleXML не поддерживает подобные структуры?

1 Ответ

0 голосов
/ 04 июня 2018

Ваш документ содержит (как минимум) два пространства имен: одно с локальным префиксом m, а другое без префикса («пространство имен по умолчанию»).На самом деле он может содержать другие пространства имен, которые вы не показывали, или переназначить префикс m: и пространство имен по умолчанию в разных точках документа, но в фрагменте, который вы показали :

  • Элемент inline находится в пространстве имен с локальным префиксом m
  • Элементы link, feed и title находятся в пространстве имен по умолчанию
  • Различные атрибуты вообще не находятся в пространстве имен ;странно, это не то же самое, что они в пространстве имен по умолчанию.

Как обсуждено в " Справочник - как мне обрабатывать пространства имен (теги и атрибуты с двоеточием в) в SimpleXML? "метод ->children() переключает пространства имен , поэтому:

  • Чтобы выбрать элемент inline, вы должны использовать ->children('m', true)->inline
  • Toвыберите элемент feed внутри него, вам нужно переключить назад в пространство имен по умолчанию, используя ->children(null, true)->feed
  • Чтобы получить доступ к элементу title внутри него, вы уже будете впространство имен по умолчанию, поэтому можно просто использовать ->title
  • В данном конкретном случае не имеет значения, находитесь ли вы в пространстве имен по умолчанию или «нет пространства имен», поэтому к атрибуту type можно получить прямой доступс ['type']
  • Не забудьте привести любой атрибут или элемент к строке, чтобы получить их строковое содержимое

Подведем итог:

$type = (string)$simpleXmlElement
    ->children('m', true)
            ->inline
    ->children(null, true)
            ->feed
            ->title
            ['type'];

Обратите внимание, что в идеале вы 'd жестко закодировать URI пространства имен, которые не подлежат изменению, а непрефиксы.Вы также можете избежать предположения о том, какое пространство имен используется по умолчанию, и явно выбирать пустое пространство имен при выборе атрибутов.Это даст вам что-то вроде этого:

$type = (string)$simpleXmlElement
    ->children(XMLNS_SOMETHING)
            ->inline
    ->children(XMLNS_OTHER_THING)
            ->feed
            ->title
    ->attributes(null)
            ->type;
...