26

What is the best way to format XML within a PHP class.

$xml = "<element attribute=\"something\">...</element>";

$xml = '<element attribute="something">...</element>';

$xml = '<element attribute=\'something\'>...</element>';

$xml = <<<EOF
<element attribute="something">
</element>
EOF;

I'm pretty sure it is the last one!

quj
  • 261
  • 1
  • 3
  • 3
  • i am not sure what you are asking. do you want to build xml using some php class? – Pramendra Gupta Sep 01 '10 at 09:18
  • I'm afraid this won't be a real XML. – fabrik Sep 01 '10 at 09:23
  • It's a webservice call for a credit card payment, some of the parameters are XML for the amount/customer address, the amount can be hardcoded as it is constant, and it's that XML that I'll type in my php class – quj Sep 01 '10 at 09:56
  • If it's a webservice, then you should not need to care about any formatting. Formatting is only useful if you need to provide the XML to humans to make it easier to read and author. Machines dont care. – Gordon Sep 01 '10 at 10:41

4 Answers4

90

With DOM you can do

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML('<root><foo><bar>baz</bar></foo></root>');
$dom->formatOutput = TRUE;
echo $dom->saveXML();

gives (live demo)

<?xml version="1.0"?>
<root>
  <foo>
    <bar>baz</bar>
  </foo>
</root>

See DOMDocument::formatOutput and DOMDocument::preserveWhiteSpace properties description.

Andrew
  • 18,680
  • 13
  • 103
  • 118
Gordon
  • 312,688
  • 75
  • 539
  • 559
16

This function works perfectlly as you want you don't have to use any xml dom library or nething just pass the xml generated string into it and it will parse and generate the new one with tabs and line breaks.

function formatXmlString($xml){
    $xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
    $token      = strtok($xml, "\n");
    $result     = '';
    $pad        = 0; 
    $matches    = array();
    while ($token !== false) : 
        if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) : 
          $indent=0;
        elseif (preg_match('/^<\/\w/', $token, $matches)) :
          $pad--;
          $indent = 0;
        elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
          $indent=1;
        else :
          $indent = 0; 
        endif;
        $line    = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
        $result .= $line . "\n";
        $token   = strtok("\n");
        $pad    += $indent;
    endwhile; 
    return $result;
}
pravat231
  • 782
  • 1
  • 11
  • 26
  • 6
    You should attribute your sources: http://recursive-design.com/blog/2007/04/05/format-xml-with-php/ – John Sheehan Dec 13 '11 at 08:16
  • Great script, just one thing to mention is, that if the xml has CDATA content, it will be also formatted, and in some cases it will break the good indentation of the whole xml. – Zsolti Apr 10 '14 at 10:43
6

//Here is example using XMLWriter

$w = new XMLWriter;
$w->openMemory();
$w->setIndent(true);
  $w->startElement('foo');
    $w->startElement('bar');
      $w->writeElement("key", "value");
    $w->endElement();
  $w->endElement();
echo $w->outputMemory();

//out put

<foo> 
 <bar> 
  <key>value</key> 
 </bar> 
</foo> 
Pramendra Gupta
  • 14,667
  • 4
  • 33
  • 34
0

The first is better if you plan to embed values into the XML, The second is better for humans to read. Neither is good if you intend really work with XML.

However if you intend to perform a simple fire and forget function that takes XML as a input parameter, then I would say use the first method because you will need to embed parameters at some point.

I personally would use the PHP class simplexml, it's very easy to use and it's built in xpath support makes detailing the data returned in XML a dream.

Mark Brown
  • 92
  • 1