note 20412 added to function.xml-parse-into-struct
| From: | dave at ovumdesign dot com | Date: | Wed, 03 Apr 2002 08:32:08 +0000 |
| Subject: | note 20412 added to function.xml-parse-into-struct | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-28529@lists.php.net to get a copy of this message | ||
Here is another variation on gdemartini@bol.com.br's nice tree algorithm. I have included
nyk@cowham.net's "cdata" suggestion. I made a few changes to suppress unitialized
variable warnings with error_reporting(E_ALL), and made a few stylistic changes.
There are two functional modifications as well. The first is the added option to expat to turn off
"case folding", since XML is technically a case-sensitive language. The second is the
returned tree - instead of returning a single-element list (an array with index 0 pointing to the
top node) like the original algorithm, it returns the top node itself. This saves you an unnecessary
level of indirection.
function xml_get_children($vals, &$i) {
$children = array();
if (isset($vals[$i]['value'])) $children[] = $vals[$i]['value'];
while (++$i < count($vals)) {
switch ($vals[$i]['type']) {
case 'cdata':
$children[] = $vals[$i]['value'];
break;
case 'complete':
$children[] = array(
'tag' => $vals[$i]['tag'],
'attributes' => isset($vals[$i]['attributes'])?
$vals[$i]['attributes'] : null,
'value' => $vals[$i]['value'],
);
break;
case 'open':
$children[] = array(
'tag' => $vals[$i]['tag'],
'attributes' => isset($vals[$i]['attributes'])?
$vals[$i]['attributes'] : null,
'children' => xml_get_children($vals, $i),
);
break;
case 'close':
return $children;
}
}
}
function xml_get_tree($file) {
$data = join('', file($file));
$parser = xml_parser_create();
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, $data, $vals, $index);
xml_parser_free($parser);
return array(
'tag' => $vals[0]['tag'],
'attributes' => isset($vals[0]['attributes'])?
$vals[0]['attributes'] : null,
'children' => xml_get_children($vals, $i = 0),
);
}
This function takes a tree returned by xml_get_tree() and simplifies it similarly to
voncken@mailandnews.com and oknapp@soly.de's suggestions. It finds any nodes that expat
considered "complete" (childless) and contain no attributes, and it moves the tag name (as
the key) and value into an element in the parent node's "values" array.
For example:
$tree = xml_get_tree('moldb.xml');
$tree = xml_condense_tree($tree);
echo $tree['children'][1]['values']['name'];
Outputs:
Lysine
function xml_condense_tree($tree) {
foreach ($tree['children'] as $index => $node) {
if (isset($node['children'])) {
$tree['children'][$index] = xml_condense_tree($node);
} elseif (isset($node['value']) and !$node['attributes']) {
$tree['values'][$node['tag']] = $node['value'];
unset($tree['children'][$index]);
}
}
if (!$tree['children']) unset($tree['children']);
return $tree;
}
Enjoy,
Dave
--
http://www.php.net/manual/en/function.xml-parse-into-struct.php
http://master.php.net/manage/user-notes.php?action=edit+20412
http://master.php.net/manage/user-notes.php?action=delete+20412
http://master.php.net/manage/user-notes.php?action=reject+20412