我想把下面的XML转换成PHP数组。有什么建议吗?
<aaaa Version="1.0">
<bbb>
<cccc>
<dddd Id="id:pass" />
<eeee name="hearaman" age="24" />
</cccc>
</bbb>
</aaaa>
我想把下面的XML转换成PHP数组。有什么建议吗?
<aaaa Version="1.0">
<bbb>
<cccc>
<dddd Id="id:pass" />
<eeee name="hearaman" age="24" />
</cccc>
</bbb>
</aaaa>
当前回答
/* Creating an XML file (Optional): Create an XML file which need to convert into the array. test.xml */ <aaaa Version="1.0"> <bbb> <cccc> <dddd Id="id:pass" /> <eeee name="hearaman" age="24" /> </cccc> </bbb> </aaaa> <?php // xml file path $path = "text.xml"; // set your according path for dynamic. // Read entire file into string $xmlfile = file_get_contents($path); // Convert xml string into an object $new = simplexml_load_string($xmlfile); // Convert into json $con = json_encode($new); // Convert into associative array $newArr = json_decode($con, true); print_r($newArr); ?> Output: Result of XML conversion to PHP Array [ 'aaaa' => [ 'bbb' => [ 'cccc' => [ 'dddd' => [ '@value' => '', '@attributes' => [ 'Id' => 'id:pass', ], ], 'eeee' => [ '@value' => '', '@attributes' => [ 'name' => 'hearaman', 'age' => '24', ], ], ], ], '@attributes' => [ 'Version' => '1.0', ], ], ]
其他回答
$array = json_decode(json_encode((array)simplexml_load_string($xml)),true);
简单!
$xml = simplexml_load_string($xmlstring, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
我知道我晚了10亿年,但我遇到了和您一样的问题,需要一个更复杂的解决方案,因此我制作了一个函数(xml_decode()),将SimpleXMLElements转换为PHP数组,同时不丢失属性,并带有参数,以便更可定制地使用。
val()函数用于自定义如何处理元素值——例如,如果您想将<elem>true</elem>转换为true而不是“true”。
免责声明:我知道只使用PHP SimpleXML扩展更容易,但我需要将许多XML文件转换为JSON文件,以便在我的一个项目中进行重大更改。此外,这个问题是关于如何将XML转换为PHP数组,而不是如何在PHP中使用XML。
<?php
function val($input) {
return strval($input);
}
/**
* Transform an SimpleXMLElement into an associative array.
*
* @param SimpleXMLElement $xml The XML element to be decoded.
*
* @param bool $attributes_key If the element attributes should be grouped into a single element.
*
* Example: <elem foo="true" bar="false" />
*
* If true, xml_decode() will output
* array("attributes" => array("foo" => "true", "bar" => "false"))
*
* If false, xml_decode() will output
* array("foo" => "true", "bar" => "false")
*
* @param bool $reduce If unecessary keys created due to XML structure should be eliminated.
*
* Example: <fruits><fruit>apple</fruit><fruit>banana</fruit></fruits>
*
* If true, xml_decode() will output the element as
* array("fruits" => array(0 => "apple", 1 => "banana"))
*
* If false, xml_decode() will output the element as
* array("fruits" => array("fruit" => array(0 => "apple", 1 => "banana")))
*
* @param array $always_array List of which childs should be treated aways as an array.
*
* Example: <fruits><fruit>apple</fruit></fruits>
*
* If array("fruit") is passed as $aways_array, xml_decode() will output the element as
* array("fruits" => array("fruit" => array(0 => "apple")))
*
* If not, xml_decode() will output the element as
* array("fruits" => array("fruit" => "apple"))
*
* @param array $value_keys List of custom element's value names. This argument is only
* used when values need to passed as elements because of attributes or other reasons.
*
* The default value key name is "value".
*
* Example: <fruits><fruit id="123">apple</fruit></fruits>
*
* If array("fruit" => "name) is passed as $value_keys, xml_decode() will output the element as
* array("fruits" => array("fruit" => array("attributes" => array("id" => "123"), "name" => "apple")))
*
* If not, xml_decode() will output the element as
* array("fruits" => array("fruit" => array("attributes" => array("id" => "123"), "value" => "apple")))
*/
function xml_decode(SimpleXMLElement $xml, bool $attributes_key = true, bool $reduce = true,
array $always_array = array(), array $value_keys = array()): string|array {
// Inicialize the array.
$arr = array();
// XML tag name.
$xml_name = $xml->getName();
// Turn attributes into elements.
foreach ($xml->attributes() as $key => $value) {
// Use a key for attributes if $attributes_key argument is true.
if ($attributes_key) {
$arr['attributes'][val($key)] = val($value);
} else {
$arr[val($key)] = val($value);
}
}
// Count children.
$children_count = $xml->children()->count();
// No children? Value will be text.
if ($children_count == 0) {
// If attributes were found and turned into elements
// the value shall be an element.
if (count($arr) > 0) {
// If attributes were found previosly.
$key = $value_keys[$xml_name] ?? $value_keys['*'] ?? "value";
$arr[$key] = val($xml);
// Else, no need for an array.
} else {
$arr = val($xml);
}
// Children? Loop continues.
} else {
// Defines if there are unecessary array keys - due to the XML structure - to be cut.
// Example: <fruits><fruit /><fruit /><fruits />
// could be turned into arr['fruits'][0] and arr['fruits'][1] instead of
// arr['fruits']['fruit'][0] and arr['fruits']['fruit'][1] for a
// cleaner organization.
$children_names = array();
foreach ($xml->children() as $child) {
$child_name = $child->getName();
in_array($child_name, $children_names) or $children_names[] = $child_name;
}
$reducible = empty($arr) && count($children_names) === 1;
foreach ($xml->children() as $child) {
// Child's name shall be the element key.
$name = $child->getName();
// Children with the same name will be turned into a list.
// Example: $arr['repeating-child'][...] = $value;
if ($xml->$name->count() > 1 || in_array($name, $always_array)) {
// Reduction, if possible and requested by the $reduce argument.
if ($reduce && $reducible) {
$arr[] = xml_decode($child, $attributes_key, $reduce, $always_array, $value_keys);
} else {
$arr[$name][] = xml_decode($child, $attributes_key, $reduce, $always_array, $value_keys);
}
// Normal children will be normally decoded.
// Example: $arr['no-repeating-child] = $value;
} else {
$arr[$name] = xml_decode($child, $attributes_key, $reduce, $always_array, $value_keys);
}
}
}
return $arr;
}
恢复所有文档和注释,函数将属性和元素值转换为简单的数组元素,并使用自身的循环来处理包含子元素的元素。
这些参数允许你:
将属性分组为单独的键; 删除由于XML结构转换而产生的不必要的键(例如:fruits->fruit to $arr['fruits']['fruit'][n]); 设置应该被视为列表的元素(因为有时它只有一个子元素,但你仍然需要它是一个列表); 为数组元素键设置一个名称,它将表示XML元素文本值——当属性转换为数组元素时将需要这个值。
XML元素的使用示例(我认为你在11年后已经解决了这个问题,但我正在回答这个问题,所以……):
test.xml
<test>
<aaaa Version="1.0">
<bbb>
<cccc>
<dddd Id="id:pass" />
<eeee name="hearaman" age="24" />
</cccc>
</bbb>
</aaaa>
</test>
PHP
$xml = simplexml_load_file("test.xml");
$decode = xml_decode($xml);
echo "<pre>" . print_r($decode,true) . "</pre>";
输出
Array
(
[aaaa] => Array
(
[attributes] => Array
(
[Version] => 1.0
)
[bbb] => Array
(
[cccc] => Array
(
[dddd] => Array
(
[attributes] => Array
(
[Id] => id:pass
)
[value] =>
)
[eeee] => Array
(
[attributes] => Array
(
[name] => hearaman
[age] => 24
)
[value] =>
)
)
)
)
)
奇怪的是没有人提到xml_parse_into_struct:
$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);
将一个XML字符串($buffer)转换为一个忽略属性的简化数组,并将具有相同名称的子元素分组:
function XML2Array(SimpleXMLElement $parent)
{
$array = array();
foreach ($parent as $name => $element) {
($node = & $array[$name])
&& (1 === count($node) ? $node = array($node) : 1)
&& $node = & $node[];
$node = $element->count() ? XML2Array($element) : trim($element);
}
return $array;
}
$xml = simplexml_load_string($buffer);
$array = XML2Array($xml);
$array = array($xml->getName() => $array);
结果:
Array
(
[aaaa] => Array
(
[bbb] => Array
(
[cccc] => Array
(
[dddd] =>
[eeee] =>
)
)
)
)
如果您还想拥有这些属性,可以通过SimpleXMLElement的JSON编码/解码使用它们。这通常是最简单快捷的解决方法:
$xml = simplexml_load_string($buffer);
$array = json_decode(json_encode((array) $xml), true);
$array = array($xml->getName() => $array);
结果:
Array
(
[aaaa] => Array
(
[@attributes] => Array
(
[Version] => 1.0
)
[bbb] => Array
(
[cccc] => Array
(
[dddd] => Array
(
[@attributes] => Array
(
[Id] => id:pass
)
)
[eeee] => Array
(
[@attributes] => Array
(
[name] => hearaman
[age] => 24
)
)
)
)
)
)
请注意,所有这些方法都只能在XML文档的名称空间中工作。