Watch Your POST: Save PHP POST Data as XML

By  on  

One of my main goals when creating PHP web forms is to keep them secure and protected from spammers and automated bots. With the amount of spam that Akismet catches every day, I don't need to be reminded of the importance of securing forms. Since 90+% of my forms are POST transmissions, I've taken a lot of time to develop POST debugging and listening code.

One function I use to keep track of POST submissions is my custom print_r_xml() function. The function takes a given array (in my case, $_POST), cycles through each key, and places each key=>value into XML format. From there, I can save the XML to a file or place the XML into a database.

The function can be used on any array ($_SESSION and $_GET would be good options too!).

The PHP Code

/* print the contents of a url */
function print_r_xml($arr,$wrapper = 'data',$cycle = 1)
{
	//useful vars
	$new_line = "\n";

	//start building content
	if($cycle == 1) { $output = '<?xml version="1.0" encoding="UTF-8" ?>'.$new_line; }
	$output.= tabify($cycle - 1).'<'.$wrapper.'>'.$new_line;
	foreach($arr as $key => $val)
	{
		if(!is_array($val))
		{
			$output.= tabify($cycle).'<'.htmlspecialchars($key).'>'.$val.'</'.htmlspecialchars($key).'>'.$new_line;
		}
		else
		{
			$output.= print_r_xml($val,$key,$cycle + 1).$new_line;
		}
	}
	$output.= tabify($cycle - 1).'</'.$wrapper.'>';

	//return the value
	return $output;
}

/* tabify */
function tabify($num_tabs)
{
	for($x = 1; $x <= $num_tabs; $x++) { $return.= "\t"; }
	return $return;
}

Notice that this function is used recursively when a value is an array.

The Usage

/* test */
$_POST = array(
				'first_name'=>'David',
				'last_name'=>'Walsh',
				'url'=>'https://davidwalsh.name',
				'languages'=>array('php','javascript','java','css'),
				'title'=>'Web Developer',
				'favorite_blogs'=>array('CSSTricks'=>'http://css-tricks.com','AJAXian'=>'http://ajaxian.com')
			);
echo print_r_xml($_POST);

The Result

<?xml version="1.0" encoding="UTF-8">
<data>
	<first_name>David</first_name>
	<last_name>Walsh</last_name>
	<url>https://davidwalsh.name</url>
	<languages>
		<0>php</0>
		<1>javascript</1>
		<2>java</2>
		<3>css</3>
	</languages>
	<title>Web Developer</title>
	<favorite_blogs>
		<CSSTricks>http://css-tricks.com</CSSTricks>
		<AJAXian>http://ajaxian.com</AJAXian>
	</favorite_blogs>
</data>

This function has been a huge help in debugging GET and POST data. Try it out, let me know what you think!

Recent Features

Incredible Demos

  • By
    Translate Content with the Google Translate API and JavaScript

    Note:  For this tutorial, I'm using version1 of the Google Translate API.  A newer REST-based version is available. In an ideal world, all websites would have a feature that allowed the user to translate a website into their native language (or even more ideally, translation would be...

  • By
    Morphing Elements Using MooTools and CSS

    Morphing an element between CSS classes is another great trick the MooTools JavaScript library enables you to do. Morphing isn't the most practical use of MooTools, but it's still a trick at your disposal. Step 1: The XHTML The block of content that will change is...

Discussion

  1. Your bloging script must have changed \n to just n in line 5:

    $new_line = “n”;

    And further on with “\t” (oh, any why not use str_repeat() instead of for?)

    Anyhow, I would recommentd using PHP_EOL instead of “\n”

  2. @BTM: You’re right, WordPress changed my newline variable. Also, I used tabify to make what I was repeating clearer. str_repeat would work just fine too.

  3. EllisGL

    Seems like overhead to take $_POST and convert the array to XML then to turn around and save it to the DB, since you would have to take the XML and turn it into an array of sorts to put each element into their the respective fields.

    If my thoughts are wrong, show me the way.

  4. @What would you propose EllisGL?

  5. I tend to use this function

    function debug($object)
    {
      echo "" . print_r($object) . "";
    }

    Not sure if this correct but just what I remember from the top of my head. (WordPress is also messing around with my pre tags.)

    Then you can just use debug($_POST). It’s not as pretty as xml but I like it.

  6. Jay

    Ya you definitely have serious overhead there, but you could have a debug flag that you keep in your config to turn on saving the xml but I agree with the uncomfortably named Jesus that what’s the point? You could have the poor man’s debugger with print_r or use something like Zend’s debugger that let’s you step through execution visual studio style.

  7. Currently, I use this script to generate XML that I place into a file. That way, I can do advanced functionality like parsing and generating reports, or simply eyeball a file when needed.

  8. EllisGL

    For *SQL – Leave the POST array as is and just call by the key name and insert into your *SQL.

    A problem you might encounter with XML in PHP will be if you are trying to process large files (>1MB), you’ll end up running out of memory. Many of times I have had to convert an XML file to a CSV with a DOS program (really quick and light), so I can load it to the DB.

  9. why don’t you use serialize($_POST) for data storing purposes? ;0)

  10. @Dan: I’m actually doing that with one project, but I want to be able to open the generated file and read it in a semi-English format. Unfortunately, my serialized data reading skills aren’t great! :)

  11. Josh

    Actually, this could be helpful with contract first web applications. Just have the user submit their request in a form, transform the POST and submit the XML to the service. I don’t have too too much experience with this, but it seems like it could work.

  12. Dave,

    You’re the man!

    I’ve been looking for a way to capture paypal IPN notifications for auditing order transactions.

    My first thought was to simply insert into a database table. but then I recalled the power of xml.

  13. any chance you can supply a download link to play with your files.
    would be much appreciated.

    Cheers

  14. Tana

    Thanks for this script, really helpful for generating dynamic templates… Still working on setting it up for my purposes but this really helped me!

  15. The \t still isn’t fixed in your Tabify function but I ended up switching to using str_repeat in any case just so I could keep everything in one contained function. Very very useful though so thank you :-)

  16. Also just noticed that your XML declaration is incorrect as it doesn’t have a proper closing tag. Line 8 should read:

    if($cycle == 1) { $output = ‘<\?xml version=”1.0″ encoding=”UTF-8″?>’.$new_line; }

    The question mark after the UTF-8 section is crucial otherwise if you send your XML as text/xml in a browser, it will break due to a parsing error “unclosed token”.

    Please note: that you’ll need to remove the backslash in front of the first question mark that I’ve highlighted in red – had to put that in to make the blog comments let me post it!!

  17. Updated, thanks Ben!

  18. Thank you Ben. My hosting provider had security restrictions in place that prevented me from adding that in “PHP” blocks.

  19. Ah I see – I’d recommend that you use something like the php function highlight_file which would allow you to put your example code in a separate file and then pull it into your blog post with full syntax highlighting – it escapes all of the code so you can echo it correctly on your page. Alternatively, as you’re using WordPress, you could use a plugin such as WP-Syntax which does essentially the same thing but has support for lots of different programming languages and custom theming.

  20. Does anyone know how to save a pushed XML post from a external company to a file on my server. And this wihout knowing the URL form the company?

  21. great help mate!
    thanks!

  22. Timmy

    Great tip. How would I reverse this process? That is, how would I take the saved XML POST data and send it to a PHP script?

  23. Delscorcho

    Hello. I am trying to create a form that allows users to upload a video file and an image file with variable text fields. I have the uploader. I have the text fields. 1) How do marry the two? 2) How do I get the information to write to an XML file? That information must include the filepath of the video file and the image file. I need the instructions to have comments with them, so that I understand what the lines of code is doing. Thank you so much for your help.

  24. Sarah

    Hey thank you for this code! I’m now learning about xml and this was very helpful. I have a question though, I would like to modify it, instead of an echo.. can I save it to an xml file that repeats keeps adding new data on each submission?

  25. FredTheWebGuy

    Dave, I just got a call from a client who asked for this functionality…and boom! here we are. Saved my hide again. As I’ve said it before: I owe you a beer. A keg, actually, at this juncture.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!