PHP SimpleXml Elements to Array
I need to send a string of html has is like
<total>
<tag>content</tag>
<tag2 ref="333">
<code>somecode</code>
<code>morecode</code>
</tag2>
<tag3> more code </tag3>
</total>
This would go into an array like :
$arra[] = "<tag>content</tag>";
$arra[] = "<tag2 ref="333">开发者_Go百科;";
$arra[] = "<code ... etc
But I'm not figuring out how to transform this data to the array.
Any tips ?
So you want to convert this tree data structure:
<total>
<tag>content</tag>
<tag2 ref="333">
<code>somecode</code>
<code>morecode</code>
</tag2>
<tag3> more code </tag3>
</total>
Into some sort of flat array:
Array
(
[0] => "<tag>content</tag>"
[1] => "<tag2 ref="333"></tag2>"
[2] => "<code>somecode</code>"
[3] => "<code>morecode</code>
[4] => "<tag3> more code </tag3> "
)
would be tricky. This is a classic CS problem that doesn't have a lot of good answerers. The tree structure provides information on the relationships between entries that a flat array or list does not. Any attempt to flatten the tree into a list will loose that referential context.
You could either explode the string and then walk through it keeping track of parent elements or ignoring them (see tag2). If I had to do something with the xml I would drop it in a SimpleXMLElement, which would produce something like this:
SimpleXMLElement Object
(
[tag] => content
[tag2] => SimpleXMLElement Object
(
[@attributes] => Array
(
[ref] => 333
)
[code] => Array
(
[0] => somecode
[1] => morecode
)
)
[tag3] => more code
)
With this I can walk it with foreach and find out the tag and it's contents. I can test to see if the contents are strings or child elements and if so walk them. A recursive function would make fairly short work of this problem. The biggest issue is how to represent the data once it flattens.
If you flatten it into the array example I provided earlier the parent and child tags loose any implied relationship to each other. If this isn't a problem, great. Write the recursive function and you are done. Here is some psudocode:
function walking($content)
$out is the array chunk that is returned
foreach $content as $tag->$data
if $value is an SimpleXMLElement
collapse $data[@attributes] into a string $attributes
append <$tag $attributes></$tag> to the end of $out
you may need to remove @attributes before recursing.
recurse into walking($data) and append the returned array to the end of $out
if $value is an Array
append <$tag></$tag> to the end of $out
recurse into walking($data) and append the returned array to the end of $out
if $value is a string
append <$tag>$value</$tag> to the end of $out
after looping through $content return $out.
However if you need to somehow keep those relationships intact you have a bit of a problem and will need to devise some sort of scheme for that
Simply:
$lines = explode('> ', $xml);
foreach($lines as $line) {
$arra[] = $line.'> ';
}
However this is assuming the sample given is an exact representation of your XML (i.e. you use > and < within the tag blocks) and not taking in consideration CDATA blocks or XML comments. http://www.w3.org/TR/REC-xml/#syntax
Otherwise I would look at the comments on the PHP.net page: http://us.php.net/manual/en/function.xml-parse.php
What exactly are you trying to do? If you give a broader picture of the problem you are trying to solve we might be able to give a better solution.
If you get the data from a file, then file() function will give you a one-line-per-row array. Could be the easiest way!
$xml = file_get_contents("../../xml/LL1234.xml");
$x = simplexml_load_string($xml);
function viewElements($x){
$Arr = $GLOBALS['Arr'];
if (count($x->attributes()) > 0 ){
$attr='';
foreach ($x->attributes() as $k => $v ){
$attr .= " $k='".$v."'";
}
}
$Arr[] = "<".$x->getName()." $attr>\n";
if (count($x->children()) > 0 ){
foreach ($x->children() as $k ){
$GLOBALS['Arr'] = $Arr;
viewElements($k);
$Arr = $GLOBALS['Arr'];
}
}else{
$Arr[] = $x[0];
}
$Arr[] = "</".$x->getName().">";
$GLOBALS['Arr'] = $Arr;
}
foreach ($x->children() as $k ){
viewElements($k);
}
foreach ($GLOBALS['Arr'] as $k ){
print $k."\n";
}
?>
Sorry for the trouble thanks to tvanover I understoud a better way of doing this the solution is bellow.
精彩评论