遍历PHP的SimpleXML对象

3

这是我的对象在使用print_r命令输出时的样子(这是由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
                            )

                    )

            )

我有一个函数,它遍历GetAttributesResult对象并创建一个关联数组,使得可以通过名称轻松引用我的字段。其中之一是data_tags,它重复了未知次数。我想将data_tags作为这些值的简单索引数组返回。以下是我的函数,但它不起作用。

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; 
}

我不确定这是否是最优雅的解决方案,但我认为它应该是可行的。array_key_exists没有返回true。我错误地测试了in_array($field-Name,$results[$x]),这样就构建了我重复的$field->Name值的数组...但它也将所有其他值转换为单个嵌套数组...所以它似乎返回true的次数比我想象的要多。虽然那里的连字符是错的,我本来想用->,它不会返回true...所以我对发生的事情非常困惑。以下是print_r显示的返回内容。
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 ) ) ) 

有没有关于如何更好地处理这个问题的指针、建议或说明……以及至少如果有人能够弄清楚我如何在其他非冗余字段上获取上述数组中的嵌套数组,那就太感激了!

这是$resultprint_r()结果: CFSimpleXML对象 ( [属性] => 数组 ( [0] => CFSimpleXML对象 ( [名称] => data_datein [值] => 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
            )

    )

)

以下是对$fieldprint_r()结果(通过<hr>标签分隔):

  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
  )

我喜欢simplexml!它是最好的 =) - Rudie
你能加上 $result 和 $field 的 print_r 吗? - Eugene
5个回答

8
在AWS PHP SDK中,您可以使用to_json(), to_stdClass()甚至to_array()从CFSimpleXML对象中获取其他数据类型。此外,对于SimpleXML对象,类型转换非常重要!
PHP有一个名为ArrayObject的对象,它是数组的面向对象版本。当您调用CFSimpleXML->to_array()时,您会得到一个CFArray对象,该对象使用额外的功能包装了本机ArrayObject对象。
$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


如果 to_json 等函数的工作方式类似于 json_encode,我有点怀疑它是否实际上会始终给出 XML 的 JSON 表示。这样做同时保留属性将始终非常丑陋或不一致。 - nairbv

0

输入代码在这里你的意思是像这样吗:

$data_tags = array();
foreach ( $select->body->GetAttributesResult AS $attr ) {
  if ( $attr->Name == 'data_tags' ) {
    $data_tags[] = $attr->Value;
  }
}

否则,我不知道你想要什么 =) 编辑
你确定 GetAttributesResult 是正确的吗?难道你的意思不是 http://www.php.net/manual/zh/simplexmlelement.attributes.php 吗?

GetAttributesResult是我正在使用的SDK返回的对象名称。除非必须,否则我不想将"data_tags"硬编码到逻辑中。任何冗余的名称--我都想转换为数组。 - Ecropolis

0

我建议这样做。

更新:

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;
}

谢谢。看起来应该可以工作...但我只得到了最后一个tag_name,而且值没有被转换成数组,所以array_key_exists可能不会评估为true。 - Ecropolis
你能否按照我之前的要求,将 $result$fieldprint_r() 添加到你的主贴中?这样会更好地理解问题,我可以提出一些可行的建议。 - Eugene
我已经添加了你要求的 print_r() 结果。 - Ecropolis
将(typecast)(字符串)添加到(array_key_exists())函数中,然后得到了(true)的结果...所以我正在取得进展。 - Ecropolis
我将发布我的最终结果,因为它有效,并且与您添加的有些不同。 - Ecropolis
显示剩余2条评论

0

我成功让这个工作了。希望对你有所帮助。

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());
        }

    }

-1
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; 
}

如果在转换过程中check为空字符串且field未设置,会发生什么情况呢?这可能会触发非法偏移量。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接