问题
Here is what my object looks like with print_r (this is an object returned by the PHP SDK for the Amazon Web Services Simple DB.
[GetAttributesResult] => CFSimpleXML Object
(
[Attribute] => Array
(
[0] => CFSimpleXML Object
(
[Name] => data_datein
[Value] => 2011-04-23
)
[1] => CFSimpleXML Object
(
[Name] => data_estatus
[Value] => 0
)
[2] => CFSimpleXML Object
(
[Name] => data_status
[Value] => 1
)
[3] => CFSimpleXML Object
(
[Name] => data_title
[Value] => Company Info
)
[4] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => firsttag
)
[5] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => secondtag
)
[6] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => thirdtag
)
[7] => CFSimpleXML Object
(
[Name] => data_files
[Value] => company_info.flv
)
[8] => CFSimpleXML Object
(
[Name] => data_id
[Value] => 8993
)
)
)
I have a function that iterates over the GetAttributesResult Object and creates an associative array that makes it easy to reference my fields by their names. One of my Names is data_tags, which is repeated an unknown number of times. I would like to return data_tags as a simple indexed array of those values. Here's my function, which doesn't work.
function attrToArray($select) {
$results = array();
$x = 0;
foreach($select->body->GetAttributesResult as $result) {
foreach ($result as $field) {
if (array_key_exists($field,$results[$x])) {
$results[$x][ (string) $field->Name ][] = (string) $field->Value;
} else {
$results[$x][ (string) $field->Name ] = (string) $field->Value;
}
}
$x++;
}
return $results;
}
I don't know if this is the most elegant solution, but I don't see why it wouldn't work. array_key_exists doesn't return true. By mistake I was able to test as in_array($field-Name,$results[$x])
and that built the array of my repeated $field->Name values... but it also converted all of the other values into single item nested array... so it would seem that it returned true more than I thought it would have. Although the hyphen in there was by mistake I meant to use -> which doesn't return true... so I'm very confused by what is going on there. Here's the print_r to show what came back.
Array ( [0] => Array (
[data_datein] => 2011-04-23
[data_estatus] => 0
[data_status] => Array ( [0] => 1 )
[data_title] => Array ( [0] => Company Info )
[data_tags] => Array (
[0] => firsttag
[1] => secondtag
[2] => thirdtag )
[data_files] => Array ( [0] => company_info.flv )
[data_id] => Array ( [0] => 8993 ) ) )
Any pointers, suggestions or instruction on how I might handle this better... and at very least if someone can figure out how I can get to the above array without the nested arrays on the other non-redundant fields. Very much appreciated!
Here is the print_r()
of $result
CFSimpleXML Object
(
[Attribute] => Array
(
[0] => CFSimpleXML Object
(
[Name] => data_datein
[Value] => 2011-04-23
)
[1] => CFSimpleXML Object
(
[Name] => data_estatus
[Value] => 0
)
[2] => CFSimpleXML Object
(
[Name] => data_title
[Value] => 0001 01 Company Name
)
[3] => CFSimpleXML Object
(
[Name] => data_status
[Value] => 1
)
[4] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => good stuff
)
[5] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => save tags
)
[6] => CFSimpleXML Object
(
[Name] => data_tags
[Value] => tagger works
)
[7] => CFSimpleXML Object
(
[Name] => data_files
[Value] => 0001_01_company_name.flv
)
[8] => CFSimpleXML Object
(
[Name] => data_id
[Value] => yFKwIxjIhH
)
)
)
and here is a print_r()
of $field
(iterated and separated by <hr>
tags.)
CFSimpleXML Object
(
[Name] => data_datein
[Value] => 2011-04-23
)
<hr>CFSimpleXML Object
(
[Name] => data_estatus
[Value] => 0
)
<hr>CFSimpleXML Object
(
[Name] => data_title
[Value] => 0001 01 Company Name
)
<hr>CFSimpleXML Object
(
[Name] => data_status
[Value] => 1
)
<hr>CFSimpleXML Object
(
[Name] => data_tags
[Value] => good stuff
)
<hr>CFSimpleXML Object
(
[Name] => data_tags
[Value] => save tags
)
<hr>CFSimpleXML Object
(
[Name] => data_tags
[Value] => tagger works
)
<hr>CFSimpleXML Object
(
[Name] => data_files
[Value] => 0001_01_company_name.flv
)
<hr>CFSimpleXML Object
(
[Name] => data_id
[Value] => yFKwIxjIhH
)
回答1:
In the AWS PHP SDK, you can use to_json(), to_stdClass() and even to_array() to get back other data types from a CFSimpleXML object. Also with SimpleXML objects, typecasting is key!
PHP has an object called ArrayObject which is more-or-less an OOP version of an array. When you call CFSimpleXML->to_array(), you get back a CFArray object, which wraps the native ArrayObject object with extra functionality.
$array = $response->body->GetAttributesResult->to_array();
list($name, $value) = $array['Attribute']->first()->map(function($node, $i) {
return (string) $node;
});
http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#i=CFSimpleXML http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#i=CFArray
回答2:
enter code here
Do you mean something like this:
$data_tags = array();
foreach ( $select->body->GetAttributesResult AS $attr ) {
if ( $attr->Name == 'data_tags' ) {
$data_tags[] = $attr->Value;
}
}
Otherwise, I don't know what you want =)
edit
Are you sure GetAttributesResult
is right? Don't you mean http://www.php.net/manual/en/simplexmlelement.attributes.php?
回答3:
I would suggest something like that.
UPDATED:
function getAttributesIntoArray( $select )
{
$results = array();
$x = 0;
foreach ( $select->body->GetAttributesResult as $result )
{
foreach ( $result as $field )
{
if ( ! isset( $results[ $x ] ) )
{
$results[ $x ] = array();
}
// Assuming, that if the $field->Value is array, then it probably have only one element
if ( $field )
{
// or if ( isset( $results[ $x ][ (string) $field->Name ] ) ) instead of array_key_exists
if ( array_key_exists( (string) $field->Name, $results[ $x ] ) )
{
$results[ $x ][ (string) $field->Name ][] = ( is_array( $field->Value ) ) ? $field->Value[0] : $field->Value;
}
else
{
$results[ $x ][ (string) $field->Name ] = ( is_array( $field->Value ) ) ? $field->Value[0] : $field->Value;
}
}
}
$x++;
}
return $results;
}
回答4:
I was able to get this one to work. Hope this helps.
protected function CFResponseToArray($response)
{
try {
if ($response->isOK()) {
$responseObj = $response->body->to_array()->getArrayCopy();
//log_message('info', print_r($responseObj, true));
$result = array();
if (isset($responseObj['SelectResult']['Item'])) {
if (is_array($responseObj['SelectResult']['Item'])) {
if (isset($responseObj['SelectResult']['Item']['Name'])) {
$itemObj = array();
//log_message('info', print_r($responseObj['SelectResult'], true));
$resultItem = $responseObj['SelectResult']['Item'];
$itemObj['Id'] = $resultItem['Name'];
$attributes = $resultItem['Attribute'];
for ($i = 0; $i < count($attributes); $i++) {
$itemObj[$attributes[$i]['Name']] = $attributes[$i]['Value'];
}
$result[] = $itemObj;
} else {
//log_message('info', print_r($responseObj['SelectResult'], true));
foreach ($responseObj['SelectResult']['Item'] as $resultItem) {
$itemObj = array();
$itemObj['Id'] = $resultItem['Name'];
$attributes = $resultItem['Attribute'];
for ($i = 0; $i < count($attributes); $i++) {
$itemObj[$attributes[$i]['Name']] = is_array($attributes[$i]['Value']) ? "" : $attributes[$i]['Value'];
}
$result[] = $itemObj;
}
if (isset($responseObj['SelectResult']['NextToken'])) {
$this->nextToken = $responseObj['SelectResult']['NextToken'];
} else {
$this->nextToken = '';
}
}
}
}
return $result;
}
} catch (exception $ex) {
log_message('error', $ex->getMessage());
}
}
回答5:
function attrToArray($select) {
$results = array();
$x = 0;
foreach ( $select->body->GetAttributesResult as $result ) {
foreach ( $result as $field ) {
$check = (string) $field->Name;
if (isset($field) && array_key_exists($check, $results[$x] ) ) {
if ( ! is_array( $results[ $x ][$check] ) ) {
$val = (string) $results[ $x ][$check];
$results[ $x ][ $check ] = array();
$results[ $x ][ $check ][] = $val;
}
$results[ $x ][ $check ][] = (string) $field->Value;
} else {
$results[ $x ][ $check ] = (string) $field->Value;
}
}
$x++;
}
return $results;
}
来源:https://stackoverflow.com/questions/5778444/iterating-over-simplexml-objext-php