XML Pretty Printer in PHP5

Today I was working with debugging some XML, and needed a way to make the XML more readable. The following is a little function that should do the job for some simple XML, and you can probably tweak it to your needs. It uses PHP5's SimpleXMLElement object to parse and return the XML, then indents it in a logical way.

Comments

Friday, May 16, 2008 / 8:54am Phoenix said…

Nice work man, pretty easy to tweak too. I got it just right to my job.

Cheers.

Monday, Jul 7, 2008 / 4:38pm WheeGuy said…

Thank you for the cute function, it saved me some time. For very linear responses (ie, no newlines) give this a shot:

1. Replace the explode's separator with '><' 2. Replace the join's separator with "> <"

Monday, Oct 13, 2008 / 3:33pm anon said…

In response to the above poster's comment:

Good start, but nothing seems to get indented like that. Maybe this is a better fix...

Replace line 16 (the line beginning with "$xml_lines") with the following:

$xml_lines = explode(" ", str_replace("><", "> <", $xml_obj->asXML()));

That's it =)

Monday, Oct 13, 2008 / 3:36pm anon said…

oops, line 12, not 16. And imagine backslash-Ns where those line breaks are (either will work).

Thursday, Oct 30, 2008 / 2:15pm Fred Trotter said…

After much fighting... I have included both the improvements from the comments above, and a trick that allows your xml pretty print function to work when xml is included in other xml which is what happens when there is an XML arguement to a soap call.

This makes your function work well against the results of SoapClient::__getLastResponse and SoapClient::__getLastRequest

This will save me a lot of time being able to directly read debug output from __getLastResponse and __getLastRequest

May this help the next googler.

function xml_pretty_printer($xml, $html_output=FALSE) { $xml_obj = new SimpleXMLElement($xml); $xml_lines = explode("\n", str_replace("><",">\n<",$xml_obj->asXML())); $indent_level = 0; $new_xml_lines = array(); foreach ($xml_lines as $xml_line) { if (preg_match('#^(<[a-z0-9_:-]+((s+[a-z0-9_:-]+="[^"]+")*)?>.*]+>)|(<[a-z0-9_:-]+((s+[a-z0-9_:-]+="[^"]+")*)?s*/s*>)#i', ltrim($xml_line))) { $new_line = str_pad('', $indent_level*4) . ltrim($xml_line); $new_xml_lines[] = $new_line; } elseif (preg_match('#^<[a-z0-9_:-]+((s+[a-z0-9_:-]+="[^"]+")*)?>#i', ltrim($xml_line))) {

$new_line = str_pad('', $indent_level*4) . ltrim($xml_line); $indent_level++; $new_xml_lines[] = $new_line; } elseif (preg_match('#/]+>#i', $xml_line)) { $indent_level--; if (trim($new_xml_lines[sizeof($new_xml_lines)-1]) == trim(str_replace("/", "", $xml_line))) { $new_xml_lines[sizeof($new_xml_lines)-1] .= $xml_line; } else { $new_line = str_pad('', $indent_level*4) . $xml_line; $new_xml_lines[] = $new_line; } } else { $new_line = str_pad('', $indent_level*4) . $xml_line; $new_xml_lines[] = $new_line; } } $xml = join("\n", $new_xml_lines); return ($html_output) ? '

' . $this->xmlspecialchars($xml) . '

' : $xml; }

function xmlspecialchars($text) { return str_replace(''', ''', htmlspecialchars($text, ENT_QUOTES, 'UTF-8',false)); }

Thursday, Oct 30, 2008 / 8:30pm Ray said…

Hey Fred,

In your last example, the whitespace tokens in the regexes are missing backslashes, resulting in indenting errors where entities have attributes. Replace 's' with 's' in those, and it's all good. :-)

Thursday, Oct 30, 2008 / 8:31pm Ray said…

Aaarrrggghhh... looks like backslashes are being stripped from posts (twice?), resulting in backslashes being removed from the comments.

Wednesday, Nov 26, 2008 / 4:43pm Kirk, the Next Googler said…

Thanks - I've been helped! Work's great after touching up the regex's.

Comments have been turned off on this blog.
Read something more recent.

Statements and opinions expressed in this blog and any comments made are the private opinions of the respective poster, and, as such, iMarc LLC is neither responsible nor liable for such content.

Meet The Author

Will Bond

Senior Tech Architect

Search

Recent Blog Posts

Recent Comments

  • A better tool

    Dave Tufts commented: Just downloaded Soulver - it's great. I also like using the search box in my browser or Google. Similar, linear layout to Soulver. (for the record, that giant calculator on my desk looked like a small regular-sized calculator in the picture on Amazon)

  • Lunchroom Banter (Volume XX)

    Nick commented: Since Bill didn't do it, I will. "Oh snap!"

  • iMarcians with staying power

    Nick commented: Congratulations on the anniversaries. I had a professor tell me early on at the Art Institute that "you can expect to change web jobs every 2-3 years until you settle somewhere". I love proving this guy wrong every day. Congrats again.

  • Twitter, Alone, Is Not Customer Service

    Jay G commented: Same here, and my story is with Alaska Air, too. Their website said the customer service phone number was open something like 8am-8pm PST, but this was after hours, so I tweeted. Lo, and behold, I got a tweet response in 10 minutes with the 24/7 phone number. But this didn't change the confusion from their website…

  • Mobile browsers: Here's the data

    Robert Mohns commented: The data comes from visitors to iMarc.net — an important detail I forgot to include! — not the web as a whole. As for why so little Flash on mobile devices… I'd say this is because even Flash Lite is pretty resource intensive, and it's just not essential to the core content most people need to access. I don't think it has a lot to do…

We heart Visitors

  • iMarc
  • 14 Inn Street
  • Newburyport, MA 01950
  • Phone: (978) 462-8848
  • Fax: (978) 462-8807
  • Directions

Contact Us

Whether you have a huge project specification or just want to talk about updating your site, we’re here to help. Fill out the form, and we’ll get right back to you.

Contact Us
  • All Fields Required

Close