Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indentation with DOMDocument in PHP

I'm using DOMDocument to generate a new XML file and I would like for the output of the file to be indented nicely so that it's easy to follow for a human reader.

For example, when DOMDocument outputs this data:

<?xml version="1.0"?> <this attr="that"><foo>lkjalksjdlakjdlkasd</foo><foo>lkjlkasjlkajklajslk</foo></this> 

I want the XML file to be:

<?xml version="1.0"?> <this attr="that">     <foo>lkjalksjdlakjdlkasd</foo>     <foo>lkjlkasjlkajklajslk</foo> </this> 

I've been searching around looking for answers, and everything that I've found seems to say to try to control the white space this way:

$foo = new DOMDocument(); $foo->preserveWhiteSpace = false; $foo->formatOutput = true; 

But this does not seem to do anything. Perhaps this only works when reading XML? Keep in mind I'm trying to write new documents.

Is there anything built-in to DOMDocument to do this? Or a function that can accomplish this easily?

like image 217
Josh Leitzel Avatar asked Apr 14 '09 03:04

Josh Leitzel


2 Answers

After some help from John and playing around with this on my own, it seems that even DOMDocument's inherent support for formatting didn't meet my needs. So, I decided to write my own indentation function.

This is a pretty crude function that I just threw together quickly, so if anyone has any optimization tips or anything to say about it in general, I'd be glad to hear it!

function indent($text) {     // Create new lines where necessary     $find = array('>', '</', "\n\n");     $replace = array(">\n", "\n</", "\n");     $text = str_replace($find, $replace, $text);     $text = trim($text); // for the \n that was added after the final tag      $text_array = explode("\n", $text);     $open_tags = 0;     foreach ($text_array AS $key => $line)     {         if (($key == 0) || ($key == 1)) // The first line shouldn't affect the indentation             $tabs = '';         else         {             for ($i = 1; $i <= $open_tags; $i++)                 $tabs .= "\t";         }          if ($key != 0)         {             if ((strpos($line, '</') === false) && (strpos($line, '>') !== false))                 $open_tags++;             else if ($open_tags > 0)                 $open_tags--;         }          $new_array[] = $tabs . $line;          unset($tabs);     }     $indented_text = implode("\n", $new_array);      return $indented_text; } 
like image 31
Josh Leitzel Avatar answered Oct 09 '22 23:10

Josh Leitzel


DomDocument will do the trick, I personally spent couple of hours Googling and trying to figure this out and I noted that if you use

$xmlDoc = new DOMDocument (); $xmlDoc->loadXML ( $xml ); $xmlDoc->preserveWhiteSpace = false; $xmlDoc->formatOutput = true; $xmlDoc->save($xml_file); 

In that order, It just doesn't work but, if you use the same code but in this order:

$xmlDoc = new DOMDocument (); $xmlDoc->preserveWhiteSpace = false; $xmlDoc->formatOutput = true; $xmlDoc->loadXML ( $xml ); $xmlDoc->save($archivoxml); 

Works like a charm, hope this helps

like image 52
Angel Avatar answered Oct 09 '22 23:10

Angel