Зацикливание на объекте SimpleXML или превращение всего объекта в массив
-
22-08-2019 - |
Вопрос
Я пытаюсь понять, как выполнить итерацию через возвращаемый объект SimpleXML.
Я использую инструментарий под названием Тарзан AWS, который подключается к Amazon Web Services (SimpleDB, S3, EC2 и т.д.).Я специально использую SimpleDB.
Я могу поместить данные в сервис Amazon SimpleDB и получить их обратно.Я просто не знаю, как обращаться с возвращаемым объектом SimpleXML.
В документации Tarzan AWS говорится следующее:
Посмотрите на ответ, чтобы перейти по заголовкам и телу ответа.Обратите внимание, что это объект, а не массив, и что тело является объектом SimpleXML.
Вот пример возвращенного объекта SimpleXML:
[body] => SimpleXMLElement Object ( [QueryWithAttributesResult] => SimpleXMLElement Object ( [Item] => Array ( [0] => SimpleXMLElement Object ( [Name] => message12413344443260 [Attribute] => Array ( [0] => SimpleXMLElement Object ( [Name] => active [Value] => 1 ) [1] => SimpleXMLElement Object ( [Name] => user [Value] => john ) [2] => SimpleXMLElement Object ( [Name] => message [Value] => This is a message. ) [3] => SimpleXMLElement Object ( [Name] => time [Value] => 1241334444 ) [4] => SimpleXMLElement Object ( [Name] => id [Value] => 12413344443260 ) [5] => SimpleXMLElement Object ( [Name] => ip [Value] => 10.10.10.1 ) ) ) [1] => SimpleXMLElement Object ( [Name] => message12413346907303 [Attribute] => Array ( [0] => SimpleXMLElement Object ( [Name] => active [Value] => 1 ) [1] => SimpleXMLElement Object ( [Name] => user [Value] => fred ) [2] => SimpleXMLElement Object ( [Name] => message [Value] => This is another message ) [3] => SimpleXMLElement Object ( [Name] => time [Value] => 1241334690 ) [4] => SimpleXMLElement Object ( [Name] => id [Value] => 12413346907303 ) [5] => SimpleXMLElement Object ( [Name] => ip [Value] => 10.10.10.2 ) ) ) )
Итак, какой код мне нужен, чтобы пройти через каждый из элементов объекта?Я бы хотел перебрать каждый из них и обработать его как возвращенный запрос MySQL.Например, я могу запросить SimpleDB, а затем выполнить цикл через SimpleXML, чтобы отобразить результаты на странице.
В качестве альтернативы, как вы превращаете весь shebang в массив?
Я новичок в SimpleXML, поэтому приношу извинения, если мои вопросы недостаточно конкретны.
Решение
Вы можете использовать SimpleXML
объект (или его свойства) в foreach
петля.Если вы хотите просмотреть все "записи", что-то вроде этого можно использовать для доступа к данным и их отображения:
//Loop through all the members of the Item array
//(essentially your two database rows).
foreach($SimpleXML->body->QueryWithAttributesResult->Item as $Item){
//Now you can access the 'row' data using $Item in this case
//two elements, a name and an array of key/value pairs
echo $Item->Name;
//Loop through the attribute array to access the 'fields'.
foreach($Item->Attribute as $Attribute){
//Each attribute has two elements, name and value.
echo $Attribute->Name . ": " . $Attribute->Value;
}
}
Обратите внимание, что $Item будет объектом SimpleXML, как и $Attribute, поэтому на них нужно ссылаться как на объекты, а не как на массивы.
В то время как приведенный выше пример кода выполняет цикл по массивам в объекте SimpleXML ($SimpleXML->body->QueryWithAttributesResult->Item), вы также можете выполнить цикл по объекту SimpleXML (скажем, $SimpleXML->body->QueryWithAttributesResult->Item[0]), и это даст вам каждое из свойств объекта.
Каждый дочерний элемент объекта SimpleXML является XML-сущностью.Если XML-объект (тег) не уникален, то элемент представляет собой просто массив объектов SimpleXML, представляющих каждый объект.
Если вы хотите, это должно создать более общий массив строк / полей из вашего объекта SimpleXML (или приблизить вас):
foreach($SimpleXML->body->QueryWithAttributesResult->Item as $Item){
foreach($Item->Attribute as $Attribute){
$rows[$Item->Name][$Attribute->Name] = $Attribute->Value;
}
}
//Now you have an array that looks like:
$rows['message12413344443260']['active'] = 1;
$rows['message12413344443260']['user'] = 'john';
//etc.
Другие советы
get_object_vars($simpleXMLElement);
одно небольшое дополнение для исправления PHP 5.2.
$response_array = json_decode(json_encode($response),true);
В случае XML-ответов, которые НЕ содержат разделов CDATA (например, Amazon / Tarzan), вы можете использовать следующее, предполагая, что у вас PHP 5.2 или новее.
// Get a SimpleXML response back from Tarzan
$s3 = new AmazonS3();
$response = $s3->list_buckets();
// Convert SimpleXML to Array in PHP 5.2.
$response_array = json_decode(json_encode($response));
Это будет стандартная утилита, доступная для всех объектов в следующей основной версии Tarzan (CloudFusion 2.5).
Почти все примеры, которые я нашел, относятся к конкретному примеру, где вы уже знаете узлы.Следующая функция преобразует SimpleXMLElement в массив, не зная имен узлов и того, есть ли у них дочерние элементы или нет.Также будет отлично работать с разделами CDATA.
function parseXML(SimpleXMLElement $xml) : array
{
$array = [];
foreach(iterator_to_array($xml, TRUE) as $key => $value)
$array[$key] = ($value->count() > 1) ? parseXML($value) : (string)$value;
return $array;
}
Это сработало:
// $result is a Simple XML object
$result = convertSimpleXMLToArray($result);
function convertSimpleXMLToArray($xml)
{
if(class_basename($xml) == 'SimpleXMLElement')
{
$xml = get_object_vars($xml);
foreach($xml as $key => $value)
{
if(class_basename($value) == 'SimpleXMLElement') $xml[$key] = convertSimpleXMLToArray($value);
}
}
return $xml;
}