xml转array
分享一个将xml文件转成数组的方法。
/**
* @purpose: 将xml转化为数组
* @param mixed $url xml文件或者xml所在的url
* @param int $getAttributes 是否获取属性值,若为true,如果xml中有attributes,将attributes存入attr里面
* @param string $priority 如果设置了$priority=tag,则标签的值作为数组中该标签作为key的value,否则会增加一级value的key
* @return array|void
*/
public static function xml2array($url, $getAttributes = true, $priority = 'tag')
{
$contents = ''; //临时保存xml内容
$arrXml = []; //xml转数组后数据存放位置
if (!function_exists('xml_parser_create')) {
goto __end;
}
$parser = xml_parser_create('');
if (!($fp = @ fopen($url, 'rb'))) {
goto __end;
}
while (!feof($fp)) {
$contents .= fread($fp, 8192);
}
fclose($fp);
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, trim($contents), $xmlValues);
xml_parser_free($parser);
if ($xmlValues) {
$current = &$arrXml;
$repeatedTagIndex = array();
foreach ($xmlValues as $data) {
//确保每次循环的时候,没有$attributes和$value这两个变量
unset ($attributes, $value);
//节点类型,open,close,complete
$type = ArrayHelper::getValue($data, 'type');
//属于几级标签,对应数组的几维
$level = ArrayHelper::getValue($data, 'level');
//xml标签名,作为数组的key
$tag = ArrayHelper::getValue($data, 'tag');
//每个标签里面的数据
$value = ArrayHelper::getValue($data, 'value');
$result = array();
$attributesData = array();
if (isset ($value)) {
if ($priority == 'tag'){
$result = $value;
}else{
$result['value'] = $value;
}
}
if (isset ($attributes) && $getAttributes) {
foreach ($attributes as $attr => $val) {
if ($priority == 'tag'){
$attributesData[$attr] = $val;
}else{
//将所有的属性以数组的形式保存在$result['attr']下面
$result['attr'][$attr] = $val;
}
}
}
//根据不同的节点类型所属维度将数据变成一个数组
if ($type == "open") {
$parent[$level - 1] = &$current;
if (!is_array($current) or (!in_array($tag, array_keys($current)))) {
$current[$tag] = $result;
if ($attributesData){
$current[$tag . '_attr'] = $attributesData;
}
$repeatedTagIndex[$tag . '_' . $level] = 1;
$current = &$current[$tag];
} else {
if (isset ($current[$tag][0])) {
$current[$tag][$repeatedTagIndex[$tag . '_' . $level]] = $result;
$repeatedTagIndex[$tag . '_' . $level]++;
} else {
$current[$tag] = [
$current[$tag],
$result,
];
$repeatedTagIndex[$tag . '_' . $level] = 2;
if (isset ($current[$tag . '_attr'])) {
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset ($current[$tag . '_attr']);
}
}
$lastItemIndex = $repeatedTagIndex[$tag . '_' . $level] - 1;
$current = &$current[$tag][$lastItemIndex];
}
} elseif ($type == "complete") {
if (!isset ($current[$tag])) {
$current[$tag] = $result;
$repeatedTagIndex[$tag . '_' . $level] = 1;
if ($priority == 'tag' && $attributesData)
$current[$tag . '_attr'] = $attributesData;
} else {
if (isset ($current[$tag][0]) && is_array($current[$tag])) {
$current[$tag][$repeatedTagIndex[$tag . '_' . $level]] = $result;
if ($priority == 'tag' && $getAttributes && $attributesData) {
$current[$tag][$repeatedTagIndex[$tag . '_' . $level] . '_attr'] = $attributesData;
}
$repeatedTagIndex[$tag . '_' . $level]++;
} else {
$current[$tag] = [
$current[$tag],
$result,
];
$repeatedTagIndex[$tag . '_' . $level] = 1;
if ($priority == 'tag' && $getAttributes) {
if (isset ($current[$tag . '_attr'])) {
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset ($current[$tag . '_attr']);
}
if ($attributesData) {
$current[$tag][$repeatedTagIndex[$tag . '_' . $level] . '_attr'] = $attributesData;
}
}
$repeatedTagIndex[$tag . '_' . $level]++; //0 and 1 index is already taken
}
}
} elseif ($type == 'close') {
$current = &$parent[$level - 1];
}
}
}
__end:
return $arrXml;
}
上面的 这几行,如果不是使用的yii框架,可用 extract($data)代替。
//节点类型,open,close,complete
$type = ArrayHelper::getValue($data, 'type');
//属于几级标签,对应数组的几维
$level = ArrayHelper::getValue($data, 'level');
//xml标签名,作为数组的key
$tag = ArrayHelper::getValue($data, 'tag');
//每个标签里面的数据
$value = ArrayHelper::getValue($data, 'value');