Possible Duplicate:
format xml string
I'm generating an XML page like so:
header('Content-Type: text/html');
$xmlpage = '<?xml version="1.0" charset="utf-8"?>';
$xmlpage .= '<conv>';
$xmlpage .= '<at>6 January 2012 12:00</at>';
$xmlpage .= '<rate>1.56317</rate>';
$xmlpage .= '<from>';
$xmlpage .= '<code>'.$from.'</code>';
$xmlpage .= '<curr>Pound Sterling</curr>';
$xmlpage .= '<loc>UK</loc>';
$xmlpage .= '<amnt>'.$amnt.'</amnt>';
$xmlpage .= '</from>';
$xmlpage .= '</conv>';
echo $xmlpage;
When viewing the page source, it looks terrible:
<?xml version="1.0" charset="utf-8"?><conv><at>6 January 2012 12:00</at><rate>1.56317</rate><from><code>USD</code><curr>Pound Sterling</curr><loc>UK</loc><amnt>23</amnt></from><to><code>GBP</code><curr>United States Dollar</curr><loc>USA</loc><amnt>14.73</amnt></to></conv>
How can I make this so it's properly formatted and indented?
Add newlines with the or only characters. You'll need to place your strings in double quotes ("") for it to work, so either replace the double-quotes inside the strings with single ones ('), escape the double quotes (\"), add ." " as a linebreak or use HEREDOC.
Building your XML with a XML generator like the built-in SimpleXML will prevent these sort and numerous other types of problems and is usually far easier than building it by hand with strings.
add a after every
$xmlpage
. You should be able to view it properly after the echo
.
e.g.
$xmlpage = "<?xml version="1.0" charset="utf-8"?>
";
$xmlpage .= "<conv>
";
$xmlpage .= "<at>6 January 2012 12:00</at>
";
$xmlpage .= "<rate>1.56317</rate>
";
You could:
, \t
).saveXML()
The first two are quick and dirty (heredoc's better). The latter is more robust, but more code.
Use a HEREDOC. it'll be far easier to read than repeated string concatenation, allows tabs/multilines, and does variable interpolation for you:
$xmlpage = <<<EOL
<?xml version="1.0" charset="utf-8"?>
<conv>
<at>6 January 2012 12:00</at>
<rate>1.56317</rate>
<from>
<code>$from</code>
<curr>Pound Sterling</curr>
<loc>UK</loc>
<amnt>$amnt</amnt>
</from>
</conv>
EOL;
The simplest way would be to add the appropriate whitespace to the beginning of the strings, and the newlines to the ends.
$xmlpage = '<?xml version="1.0" charset="utf-8"?>';
$xmlpage .= '<conv>' . "
";
$xmlpage .= "\t" . '<at>6 January 2012 12:00</at>' . "
";
$xmlpage .= "\t" . '<rate>1.56317</rate>' . "
";
$xmlpage .= '<from>' . "
";
$xmlpage .= "\t" . '<code>'.$from.'</code>' . "
";
$xmlpage .= "\t" . '<curr>Pound Sterling</curr>' . "
";
$xmlpage .= "\t" . '<loc>UK</loc>' . "
";
$xmlpage .= "\t" . '<amnt>'.$amnt.'</amnt>' . "
";
$xmlpage .= '</from>' . "
";
$xmlpage .= '</conv>';
Or something along those lines, depending on your desired output.
Here's my prettify function, which formats for output. You can modify it to suit your needs.
function prettifyXML( $xml )
{
// Break our XML up into sections of newlines.
$xml = preg_replace( '/(<[^\/][^>]*?[^\/]>)/', "
" . '\1', $xml );
$xml = preg_replace( '/(<\/[^\/>]*>|<[^\/>]*?\/>)/', '\1' . "
", $xml );
$xml = str_replace( "
", "
", $xml );
$xml_chunks = explode( "
", $xml );
$indent_depth = 0;
$open_tag_regex = '/<[^\/\?][^>]*>/';
$close_tag_regex = '/(<\/[^>]*>|<[^>]*\/>)/';
// Fix the indenting.
foreach ( $xml_chunks as $index => $xml_chunk )
{
$close_tag_count = preg_match( $close_tag_regex, $xml_chunk );
$open_tag_count = preg_match( $open_tag_regex, $xml_chunk );
if ( $open_tag_count >= $close_tag_count )
{
$temp_indent_depth = $indent_depth;
}
else
{
$temp_indent_depth = $indent_depth - $close_tag_count;
}
$xml_chunks[ $index ] = str_repeat( "\t", $temp_indent_depth ) . $xml_chunk;
$indent_depth += $open_tag_count - $close_tag_count;
}
$xml = implode( "
", $xml_chunks );
// Add tokens for attributes and values.
$attribute_regex = '/([\w:]+\="[^"]*")/';
$value_regex = '/>([^<]*)</';
$value_span_token = '##@@##@@';
$attribute_span_token = '@@##@@##';
$span_close_token = '#@#@#@#@';
$xml = preg_replace( $value_regex, '>' . $value_span_token . '\1' . $span_close_token . '<', $xml );
$xml = preg_replace( $attribute_regex, $attribute_span_token . '\1' .$span_close_token, $xml );
$xml = htmlentities( $xml );
// Replace the tokens that we added previously with their HTML counterparts.
$xml = str_replace( $value_span_token, '<span class="value">', $xml );
$xml = str_replace( $attribute_span_token, '<span class="attribute">', $xml );
$xml = str_replace( $span_close_token, '</span>', $xml );
return $xml;
}
It's been relatively well tested to handle edge cases, though it's not highly efficient because it's only for viewing logs.
Use a stylesheet and an XML viewer to view it.