Friday, February 24, 2012

Beautify an XML string in PHP (PCRE)

/*
 * Beautify an XML string.
 *
 * @param    string    Compressed/Unformatted XML string
 * @return   string    Formatted XML string
 */
function beautifyXmlString ( $xml )
{
    
// add marker linefeeds to aid the pretty-tokeniser
    // (adds a linefeed between all tag-end boundaries)
    
$xml = preg_replace ( '/(>)(<)(\/*)/', "$1\n$2$3", $xml );

    
// now indent the tags
    
$token = strtok ( $xml, "\n" );
  
    
// holds formatted version as it is built
    
$result = '';
  
    
// initial indent
    
$pad = 0;
  
    
// returns from preg_matches()
    
$matches = array();

    
// scan each line and adjust indent based on opening/closing tags
    
while ( $token !== false )
    {  
        
// test for the various tag states

        // 1. open and closing tags on same line - no change
        
if ( preg_match ( '/.+<\/\w[^>]*>$/', $token, $matches ) ) :
            
$indent = 0;

        
// 2. closing tag - outdent now
        
elseif ( preg_match ( '/^<\/\w/', $token, $matches ) ) :
            
$pad--;

        
// 3. opening tag - don't pad this one, only subsequent tags
        
elseif ( preg_match ( '/^<\w[^>]*[^\/]>.*$/',
                 
$token, $matches ) ) :
            
$indent=1;

        
// 4. no indentation needed
        
else :
            
$indent = 0;

        endif;

        
// pad the line with the required number of leading spaces
        
$line = str_pad ( $token, strlen ( $token ) +
                
$pad, "\t", STR_PAD_LEFT );
                 
        
// add to the cumulative result, with linefeed
        
$result .= $line . "\n";
      
        
// get the next token
        
$token = strtok ( "\n" );
      
        
// update the pad size for subsequent lines
        
$pad += $indent;
    }
    return 
$result;
}

/*
 +-----------+
 |  Example  |
 +-----------+
*/
echo beautifyXmlString ( '<response><post><title>Damn in the World'.
                         
'</title></post></response>' );
/*
 +-----------+
 |  Output   |
 +-----------+
*/
/*
<response>
    <post>
        <title>Damn in the World</title>
    </post>
</response>
*/

0 comments:

Post a Comment