У меня есть PHP-скрипт, который загружает XML-лист следующим образом:
$feed = 'mydata.xml';
$xml = file_get_contents($feed);
$data = simplexml_load_string($xml);
echo print_r($data);
Результат выглядит так (хотя я многое изрубил):
SimpleXMLElement Object
(
[merchant] => SimpleXMLElement Object
(
[@attributes] => Array
(
[id] => 1
[name] => companyname
)
[prod] => Array
(
[0] => SimpleXMLElement Object
(
[@attributes] => Array
(
[id] => 690579815
[lang] => en
[pre_order] => no
[web_offer] => yes
[in_stock] => yes
)
Мой вопрос: как я могу получить доступ к массиву prod? Я хочу, чтобы это можно было считать так:
count($data['prod']);
А также получить определенные значения полей, но я совершенно новичок в PHP и XML и не могу это сделать.
Благодарю!
Мой вопрос: как я могу получить доступ к массиву prod?
Вы не можете. Потому что нет массива. Но все в порядке, спросите вы, просто print_r
немного вас обманывает. SimpleXMLElement - это объект, и он может изменить то, что будет показано при получении print_r
'ed, и это подделает вам некоторые массивы.
Некоторые основы для спасения:
$data
представляет собой элемент документа XML, который у вас есть. В случае, если вы сомневаетесь в том, что в XML вместо print_r
загляните в $data->asXML()
(если вы просматриваете источник просмотра браузера или намекаете на вывод как обычный текст, в противном случае браузер скроет все теги).
$data['prod']
дает вам атрибут с именем prod для этого элемента документа. Поскольку его нет, он возвращает null
:
var_dump($data['prod']); --- NULL
И count
NULL
равно 0:
var_dump(count(NULL)); --- int(0)
Вы не хотите заглядывать в элемент документа и не хотите искать атрибуты. Вас интересуют дочерние элементы с именем prod внутри элемента торговца.
Итак, сначала получите первый купеческий элемент:
$merchant = $data->merchant;
Вы получаете элементы с доступом к объекту, то есть с оператором объекта ->
.
И получите счетчик числа дочерних элементов с именем prod:
var_dump(count($merchant->prod)); --- int(3)
Как показано на рисунке, у меня есть три (3) детей с именем prod внутри элемента торговца, представленного $merchant
.
Таким образом, вам не нужен массив, SimpleXMLElement позволяет получить доступ ко всем XML-элементам внутри документа XML.
Как было написано ранее, скобки массива используются для доступа к массиву. Таким образом, он выглядит как массив, но на самом деле это объект. Он используется для доступа к атрибутам. Но это верно только в том случае, если ключ не является числом. Если это число, он будет обращаться к n-му именованному элементу:
var_dump($merchant->prod[0]->asXML());
Дает XML первого элемента prod элемента торговца:
string(94) "<prod id="690579815" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #1</prod>"
Поскольку это первый элемент, вы также можете получить его атрибут id:
var_dump($merchant->prod[0]['id']->asXML());
Что возвращает именно этот атрибут:
string(15) " id="690579815""
Но здесь это не останавливается. Каждый из этих объектов SimpleXMLElement элементов и атрибутов XML можно обвести в строку:
var_dump((string)$merchant->prod[0]); --- string(10) "product #1"
var_dump((string)$merchant->prod[0]['id']); --- string(9) "690579815"
Чаще всего это фактическая информация, которую вы ищете. Когда вы используете echo
или подобное, это строковое кастинг выполняется автоматически btw.
echo $merchant->prod[0]; // prints: "product #1"
Подобно массивам (и объекту), вы также можете перебирать каждый элемент SimpleXMLElement. Например, элемент $merchant
:
foreach ($merchant as $children)
{
echo $children->asXML(), "\n";
}
дает:
<merchant id="1" name="companyname">
<prod id="690579815" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #1</prod>
<prod id="250544605" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #2</prod>
<prod id="360355798" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #3</prod>
</merchant>
Это единственный элемент. Настолько интереснее это с именованными дочерними элементами:
foreach ($merchant->prod as $prod)
{
echo $prod->asXML(), "\n";
}
Теперь это дает всем детям по имени prod один за другим:
<prod id="690579815" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #1</prod>
<prod id="250544605" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #2</prod>
<prod id="360355798" lang="en" pre_order="no" web_offer="yes" in_stock="yes">product #3</prod>
Вы найдете это, как объяснено в Basic SimpleXML, в руководстве по PHP. Проконсультируйтесь с ним как с другим источником.
Просто соблюдайте следующие правила:
print_r
и var_dump
обманывают вас при использовании с SimpleXMLElementЧтобы получить доступ к нему как ассоциативный массив, сделайте следующее:
$data = json_decode(json_encode($data), true);
то вы можете получить к нему доступ так:
count($data['merchant']['prod'])
$data['merchant']['prod'][0]['id]
SimpleXMLElement
- это объект, поэтому вам также нужно обращаться к ним как к объекту:
print count($data->merchant->prod);
$data
- это не массив, это экземплярSimpleXMLElement
, используйте его соответственно:$data->merchant->prod[0];