views:

444

answers:

5

Hello, 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">";
$arra[] = "<code ... etc

But I'm not figuring out how to transform this data to the array.

Any tips ?

+1  A: 

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

Ryan Schumacher
+1  A: 

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.

Niels Bom
A: 

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

tvanover
I'm trying to what you have shown, my problem is dealing with end tags at the moment , the xml is constructed previously with php DomDocument.
netcrash
A: 

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!

Aif
A: 
$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.

netcrash