我正在尝试遍历一个xml文件,并将节省了它的值保存到一个数组中(key => value)。我还希望它跟踪它传递的节点(类似于array(users_user_name =>“myName”,users_user_email =>“myEmail”)等)。
我知道怎么做但是有一个问题。所有的节点都可以有孩子,那些孩子也可能有孩子等。所以我需要某种递归功能来保持孩子们的循环直到它到达最后一个孩子。
到目前为止我得到了这个:
//loads the xml file and creates simpleXML object
$xml = simplexml_load_string($content);
// for each root value
foreach ($xml->children() as $children) {
// for each child of the root node
$node = $children;
while ($children->children()) {
foreach ($children as $child) {
if($child->children()){
break;
}
$children = $node->getName();
//Give key a name
$keyOfValue = $xml->getName() . "_" . $children . "_" . $child->getName();
// pass value from child to children
$children = $child;
// no children, fill array: key => value
if ($child->children() == false) {
$parent[$keyOfValue] = (string)$child;
}
}
}
$dataObject[] = $parent;
}
“休息”是为了防止它给我错误的值,因为“child”是一个对象,而不是最后一个孩子。
使用递归,你可以写一些“复杂”的处理,但问题是失去你的位置。
我在这里使用的函数传递了几个东西来跟踪名称和当前输出,以及它当前正在使用的节点。如您所见 - 该方法检查是否存在任何子节点,并再次调用该函数来处理它们中的每一个。
$content = <<< XML
<users>
<user>
<name>myName</name>
<email>myEmail</email>
<address><line1>address1</line1><line2>address2</line2></address>
</user>
</users>
XML;
function processNode ( $base, SimpleXMLElement $node, &$output ) {
$base[] = $node->getName();
$nodeName = implode("_", $base);
$childNodes = $node->children();
if ( count($childNodes) == 0 ) {
$output[ $nodeName ] = (string)$node;
}
else {
foreach ( $childNodes as $newNode ) {
processNode($base, $newNode, $output);
}
}
}
$xml = simplexml_load_string($content);
$output = [];
processNode([], $xml, $output);
print_r($output);
打印出......
Array
(
[users_user_name] => myName
[users_user_email] => myEmail
[users_user_address_line1] => address1
[users_user_address_line2] => address2
)
通过此实现,内容存在限制 - 例如 - 重复内容将仅保留最后一个值(例如,有多个用户)。
你会想要使用递归!
这是递归的一个简单示例:
function doThing($param) {
// Do what you need to do
$param = alterParam($param);
// If there's more to do, do it again
if ($param != $condition) {
$param = doThing($param);
}
// Otherwise, we are ready to return the result
else {
return $param;
}
}
您可以将此思维应用于您的特定用例。
//Using SimpleXML library
// Parses XML but returns an Object for child nodes
public function getNodes($root)
{
$output = array();
if($root->children()) {
$children = $root->children();
foreach($children as $child) {
if(!($child->children())) {
$output[] = (array) $child;
}
else {
$output[] = self::getNodes($child->children());
}
}
}
else {
$output = (array) $root;
}
return $output;
}