循环一个 SimpleXML 对象,或者把整个对象变成一个数组

Posted

技术标签:

【中文标题】循环一个 SimpleXML 对象,或者把整个对象变成一个数组【英文标题】:Looping through a SimpleXML object, or turning the whole thing into an array 【发布时间】:2010-10-26 15:57:40 【问题描述】:

我正在尝试研究如何通过返回的 SimpleXML 对象进行迭代。

我正在使用一个名为 Tarzan AWS 的工具包,它连接到 Amazon Web Services(SimpleDB、S3、EC2 等)。我专门使用 SimpleDB。

我可以将数据放入 Amazon SimpleDB 服务,然后我可以取回它。我只是不知道如何处理返回的 SimpleXML 对象。

Tarzan AWS 文档是这样说的:

查看响应以浏览响应的标头和正文。请注意,这是一个对象,而不是数组,并且主体是一个 SimpleXML 对象。

这是返回的 SimpleXML 对象的示例:

[body] => SimpleXMLElement 对象 ( [QueryWithAttributesResult] => SimpleXMLElement 对象 ( [项目] => 数组 ( [0] => SimpleXMLElement 对象 ( [名称] => 消息12413344443260 [属性] => 数组 ( [0] => SimpleXMLElement 对象 ( [名称] => 活跃 [值] => 1 ) [1] => SimpleXMLElement 对象 ( [名称] => 用户 [价值] => 约翰 ) [2] => SimpleXMLElement 对象 ( [名称] => 消息 [值] => 这是一条消息。 ) [3] => SimpleXMLElement 对象 ( [名称] => 时间 [价值] => 1241334444 ) [4] => SimpleXMLElement 对象 ( [名称] => 身份证 [价值] => 12413344443260 ) [5] => SimpleXMLElement 对象 ( [名称] => ip [值] => 10.10.10.1 ) ) ) [1] => SimpleXMLElement 对象 ( [名称] => 消息12413346907303 [属性] => 数组 ( [0] => SimpleXMLElement 对象 ( [名称] => 活跃 [值] => 1 ) [1] => SimpleXMLElement 对象 ( [名称] => 用户 [价值] => 弗雷德 ) [2] => SimpleXMLElement 对象 ( [名称] => 消息 [值] => 这是另一条消息 ) [3] => SimpleXMLElement 对象 ( [名称] => 时间 [价值] => 1241334690 ) [4] => SimpleXMLElement 对象 ( [名称] => 身份证 [价值] => 12413346907303 ) [5] => SimpleXMLElement 对象 ( [名称] => ip [值] => 10.10.10.2 ) ) ) )

那么我需要什么代码来遍历每个对象项?我想遍历它们中的每一个并像返回的 mysql 查询一样处理它。例如,我可以查询 SimpleDB,然后通过 SimpleXML 循环,以便在页面上显示结果。

或者,你如何将整个 shebang 变成一个数组?

我是 SimpleXML 的新手,所以如果我的问题不够具体,我深表歉意。

【问题讨论】:

【参考方案1】:

您可以在foreach 循环中使用SimpleXML 对象(或其属性)。如果您想遍历所有“记录”,可以使用类似这样的方法来访问和显示数据:

//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.

【讨论】:

非常感谢。它工作得很好。一个简单的问题。使用第一个示例,我如何仅回显 $Attribute->Value 中的一个,而不是全部回显。我已经尝试过 echo $Attribute->Name['xx']、循环中的循环等各种事情。我有些困惑。甚至可能吗?还是我只需要 if($Attribute->Value == "xx") 语句? 我不知道 SimpleXML 提供了您正在做的事情的快捷方式(在循环时测试值)。【参考方案2】:
get_object_vars($simpleXMLElement);

【讨论】:

谢谢,我试图在不知道子元素名称的情况下使用 foreach 循环,但它不会让我这样做。在这个功能之后它完美地工作了【参考方案3】:

php 5.2 修复添加了一点点。

$response_array = json_decode(json_encode($response),true);

【讨论】:

11 年后,仍然是一个很好的提示【参考方案4】:

对于不包含 CDATA 部分的 XML 响应(如 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) 中所有对象都可以使用的标准实用程序。

【讨论】:

【参考方案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;

【讨论】:

【参考方案6】:

这行得通:

// $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;

【讨论】:

以上是关于循环一个 SimpleXML 对象,或者把整个对象变成一个数组的主要内容,如果未能解决你的问题,请参考以下文章

PHP 5 SimpleXML 函数

PHP SimpleXML 对象中的属性消失?

如何序列化/反序列化 SimpleXML 对象?

从 SimpleXML 对象到数组的递归转换

使用 SimpleXML 从头开始​​创建 XML 对象

如何将更改的 SimpleXML 对象保存回文件?