我的服务器代码如下:
<?php
$xml_data='<Player uID="p59936">
<Name>Wojciech Szczesny</Name>
<Position>Goalkeeper</Position>
<Stat Type="first_name">Wojciech</Stat>
<Stat Type="last_name">Szczesny</Stat>
<Stat Type="birth_date">1990-04-18</Stat>
<Stat Type="birth_place">Warszawa</Stat>
<Stat Type="first_nationality">Poland</Stat>
<Stat Type="weight">84</Stat>
<Stat Type="height">196</Stat>
<Stat Type="jersey_num">1</Stat>
<Stat Type="real_position">Goalkeeper</Stat>
<Stat Type="real_position_side">Unknown</Stat>
<Stat Type="join_date">2008-07-01</Stat>
<Stat Type="country">Poland</Stat>
</Player>';
$xml = simplexml_load_string($xml_data);
$array = json_decode(json_encode($xml),true);
echo "<pre>";print_r($array);exit;
?>
但现在我得到的结果是:
Array
(
[@attributes] => Array
(
[uID] => p59936
)
[Name] => Wojciech Szczesny
[Position] => Goalkeeper
[Stat] => Array
(
[0] => Wojciech
[1] => Szczesny
[2] => 1990-04-18
[3] => Warszawa
[4] => Poland
[5] => 84
[6] => 196
[7] => 1
[8] => Goalkeeper
[9] => Unknown
[10] => 2008-07-01
[11] => Poland
)
)
所以我得到的不是像first_name
、last_name
这样的密钥,而是像0,1,2...
这样的密钥
那么如何获取XML中指定的密钥呢?
首先,实际上不需要json_encode/解码。您已经可以使用SimpleXML
遍历所需的值。
print_r
是误导性的,你可能会认为在转储之后,那些Type
属性就不见了,但它们仍然存在。这里有一个雄辩的答案来讨论这个问题。
但如果你想获得这些值,你可以这样做(注意有很多方法可以获得):
$xml = simplexml_load_string($xml_data);
foreach($xml->Stat as $stat) {
$type = (string) $stat->attributes()->Type;
$node_value = (string) $stat;
echo "$type: $node_value <br/>";
}
样本输出
缺少属性的原因是json_encode
。当你仔细观察它时,你会发现,编码吞噬了属性Type
$json = json_encode($xml);
print_r($json);
将显示
{"@attributes":{"uID":"p59936"},"Name":"Wojciech Szczesny","Position":"Goalkeeper","Stat":["Wojcierh","Szczersny","1990-04-18","Warszawa","Poland","84","196","1","Goalkeeper","Unknown","2008-07-01","波兰"]}
另请参阅json_encode
手册页面上的此注释。
但正如@Ghost已经指出的那样,属性仍然存在于$xml
中,随时可以检查。
这可以通过更改json_serialize
上的对象行为来实现,例如,通过查找标记名称,然后更改返回的数据:
class MyJson extends SimpleXMLElement implements JsonSerializable
{
public function jsonSerialize() {
$name = $this->getName();
if ($name !== 'Player') {
return $this;
}
$data = [];
foreach ($this as $name => $element) {
if ($name === 'Stat') {
$name = (string) $element['Type'];
}
$data[$name] = (string) $element;
}
return $data;
}
}
$xml = simplexml_load_string($buffer, 'MyJson');
$array = json_decode(json_encode($xml), true);
print_r($array);
这会产生以下输出:
Array
(
[Name] => Wojciech Szczesny
[Position] => Goalkeeper
[first_name] => Wojciech
[last_name] => Szczesny
[birth_date] => 1990-04-18
[birth_place] => Warszawa
[first_nationality] => Poland
[weight] => 84
[height] => 196
[jersey_num] => 1
[real_position] => Goalkeeper
[real_position_side] => Unknown
[join_date] => 2008-07-01
[country] => Poland
)
另一种选择是在将文档序列化为JSON(然后返回到数组)之前修改文档。
以下示例将所有<Stat>
元素转换为以包含原始<Stat>
元素值的Type
属性命名的元素。然后移除<Stat>
元素:
$xml = simplexml_load_string($buffer);
foreach ($xml->xpath("//Player/Stat") as $stat) {
$parent = $stat->xpath('..')[0];
$parent->addChild((string) $stat["Type"])[0] = trim($stat);
unset($stat[0]);
}
$array = json_decode(json_encode($xml), true);
print_r($array);
此示例产生以下输出:
Array
(
[@attributes] => Array
(
[uID] => p59936
)
[Name] => Wojciech Szczesny
[Position] => Goalkeeper
[first_name] => Wojciech
[last_name] => Szczesny
[birth_date] => 1990-04-18
[birth_place] => Warszawa
[first_nationality] => Poland
[weight] => 84
[height] => 196
[jersey_num] => 1
[real_position] => Goalkeeper
[real_position_side] => Unknown
[join_date] => 2008-07-01
[country] => Poland
)
这只是两个例子。两者都可以创建相同的输出,它只是显示了两个不同的位置,您可以在其中放置转换文档的逻辑。
相关资源:
- 当有一个子组时,PHP将XML转换为JSON组
- 使用SimpleXMLElement从对象获取数组