27

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!

4
  • i am not sure what you are asking. do you want to build xml using some php class? Commented Sep 1, 2010 at 9:18
  • I'm afraid this won't be a real XML. Commented Sep 1, 2010 at 9: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 Commented Sep 1, 2010 at 9: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. Commented Sep 1, 2010 at 10:41

5 Answers 5

93

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.

Sign up to request clarification or add additional context in comments.

Comments

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;
}

2 Comments

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.
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> 

1 Comment

Btw, XMLWriter is better than the DOM functions? Looks nicer though.
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.

Comments

0

The above function formatXmlString is a great job ! Thanks! I updated it so one can use any symbol for indentation and also encode tags for displaying the code on a web page. Here's the new code and an example.

Just replace these lines into the above code

function formatXmlString( $xml = "", $indent_symbol = " ", $crlf = "\n", $bool_enc_tags = 0 )

$line = str_pad($token, strlen($token)+$pad * $indent_symbol_len, $indent_symbol, STR_PAD_LEFT);

After the while-loop, put the following

if ( $bool_enc_tags )
{
     $result = str_replace( "<", "&lt;", $result );
     $result = str_replace( ">", "&gt;", $result );
}

if ( $crlf != "\n" )
$result = preg_replace( "/\n/", $crlf, $result );

return $result;

Then test it as below

echo formatXmlString( '<root><foo><bar>baz</bar></foo></root>', str_repeat( "&nbsp;", 4 ), "<br/>", true );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.