Creating XML file from HTML form - php

Ok so I got it working, now the only problem is when a new submission is added it overwrites the previous entry. I need it to add the newest submission to the XML file and not over ride it and store it for X amount of time.
Here is the working php script that creates the xml file and takes the data from the HTML form and puts it in the XML file.
<?php
if (isset($_POST['lsr-submit']))
{
header('Location: http://www.mesquiteweather.net/wxmesqLSR.php');
}
$str = '<?xml version="1.0" encoding="UTF-8"?><entrys></entrys>';
$xml = simplexml_load_string($str);
$fname = $_POST['firstname'];
$lname = $_POST['lastname'];
$location = $_POST['location'];
$report = $_POST['report'];
$description = $_POST['desc'];
$fname = htmlentities($fname, ENT_COMPAT, 'UTF-8', false);
$lname = htmlentities($lname, ENT_COMPAT, 'UTF-8', false);
$location = htmlentities($location, ENT_COMPAT, 'UTF-8', false);
$report = htmlentities($report, ENT_COMPAT, 'UTF-8', false);
$description = htmlentities($description, ENT_COMPAT, 'UTF-8', false);
$xml->reports = "";
$xml->reports->addChild('fname', $fname);
$xml->reports->addChild('lname', $lname);
$xml->reports->addChild('location', $location);
$xml->reports->addChild('report', $report);
$xml->reports->addChild('description', $description);
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$doc->preserveWhiteSpace = true;
$doc->loadXML($xml->asXML(), LIBXML_NOBLANKS);
$doc->save('test2.xml');
?>
Here is the xml file it creates.
XML FILE
Here is the form to submit to the XML file. Submit a test submission and it takes you to the page to display but you'll notice it will overwrite the last one instead of adding to the XML file.
HTML FORM

This is what I came up with and works well, and tested.
NOTE: However if the file (file.xml) does not exist, it will throw off an error, so if you figure out a way to automatically delete the old file(s) via CRON or any other method (you mentioned: "...and store it for X amount of time."), you'll have to come up with a way to make a pre-built structured file with at least one set of entries inside it.
E.g.:
<?xml version="1.0" encoding="UTF-8"?>
<entries>
<reports>
<timestamp>May 31, 2013, 11:56 am</timestamp>
<fname>Fred</fname>
<lname>Fletcher</lname>
<location>Canada</location>
<report>Wind Damage</report>
<description>Winds were gusting mighty hard today!</description>
</reports>
</entries>
This is relatively easy to do, I've done it before with an if file exists....
Here is my working code:
<?php
// Script by Fred Fletcher, Canada.
$fname = $_POST['firstname'];
$lname = $_POST['lastname'];
$location = $_POST['location'];
$report = $_POST['report'];
$description = $_POST['desc'];
$xml = new DOMDocument('1.0', 'utf-8');
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->load('file.xml');
$element = $xml->getElementsByTagName('reports')->item(0);
$timestamp = $element->getElementsByTagName('timestamp')->item(0);
$fname = $element->getElementsByTagName('fname')->item(0);
$lname = $element->getElementsByTagName('lname')->item(0);
$location = $element->getElementsByTagName('location')->item(0);
$report = $element->getElementsByTagName('report')->item(0);
$description = $element->getElementsByTagName('description')->item(0);
$newItem = $xml->createElement('reports');
$newItem->appendChild($xml->createElement('timestamp', date("F j, Y, g:i a",time())));;
$newItem->appendChild($xml->createElement('fname', $_POST['firstname']));
$newItem->appendChild($xml->createElement('lname', $_POST['lastname']));
$newItem->appendChild($xml->createElement('location', $_POST['location']));
$newItem->appendChild($xml->createElement('report', $_POST['report']));
$newItem->appendChild($xml->createElement('description', $_POST['desc']));
$xml->getElementsByTagName('entries')->item(0)->appendChild($newItem);
$xml->save('file.xml');
echo "Data has been written.";
?>
A "plug" as a comment in the script would be nice, "Script by Fred Fletcher, Canada." (wink)
Let me know how this works out for you.

I am not sure I got your question, but if you need to create a file that is unique for each submission then you cannot simply use echo, you must actually create a file.
Also if after submitting you redirect to another PHP file, how can you handle the data to write into the variables?
Example for creating a file:
<?php // testfile.php
$fh = fopen("testfile.xml", 'w') or die("Failed to create file");
$text = <<<_END
Line 1
Line 2
Line 3
_END;
fwrite($fh, $text) or die("Could not write to file");
fclose($fh);
?>

Related

When appending to the end of the XML, the formatOutput doesn't work but when first creating the file, the formatOutput works fine

This may sound pretty basic but right now I am very confused.
Right now I'm using php to create an XML file, first I check if the file exists, and if he doesn't I create the file with the first entry created, but if the XML file does already exist, then ill will just append the data. The data is being appended when needed and the file is being created without any bugs, but the only small problem I am having is that when I append the data to the end of the file, it won't format to regular waterfall format it has, instead it just appends it in one line. Here is my php code:
<?php
$id = $_POST['id_from'];
$id_to = $_POST['userid_to'];
$content = $_POST['message'];
$time = $_POST['time'];
$xml = new DOMDocument("1.0");
$xml->formatOutput = true;
$filename = 'chats/'.$id.'-'.$id_to.'.xml';
if(file_exists($filename)){
$xml->load($filename);
$messages = $xml->getElementsByTagName('messages')->item(0);
$message = $xml->createElement("message");
$messages->appendChild($message);
$content = $xml->createElement("content", $content);
$message->appendChild($content);
$to = $xml->createElement("to", $id_to);
$message->appendChild($to);
$from = $xml->createElement("from", $id);
$message->appendChild($from);
}else{
//creating root
$messages = $xml->createElement('messages');
$xml->appendChild($messages);
$message = $xml->createElement("message");
$messages->appendChild($message);
$content = $xml->createElement("content", $content);
$message->appendChild($content);
$to = $xml->createElement("to", $id_to);
$message->appendChild($to);
$from = $xml->createElement("from", $id);
$message->appendChild($from);
}
$xml->save($filename) or die("error");
?>
And below is a picture of my xml file.
Thank you very much!
Image of my xml file
You need to disabled whitespaces preservation before loading the file, so DOMDocument can do its own business without trying to keep the original format in place.
$xml = new DOMDocument("1.0");
$xml->preserveWhiteSpace = false ;
$xml->formatOutput = true;

Pipe email - read from stdin - get html table cells values in array - connect to drupal - create new node doesnt seem to work

Title of this question explains the workflow i am trying to achieve.
So i have made email piping to script.php in my c-panel. It works, even though it always returns message: "Mail delivery failed: local delivery failed" to the sender email. But that's not an issue her, i guess :)
I have tested piping with a test script:
#!/usr/bin/php -q
<?php
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$email .= fread($fd, 1024);
}
fclose($fd);
$filename = rand(7, 100000).'email'.time();
$fdw = fopen("/home/user/public_html/project/emails/" . $filename, "w+");
fwrite($fdw, $email);
fclose($fdw);
?>
As a result i get .txt file which contains all the email content.
Lets go further: Now i use this script to capture previously created file, parse it (get all the html table cell values, which is in email body region) and then connect to drupal and finally create node containing html table cell value information:
#!/usr/bin/php -q
<?php
$email = file_get_contents("emails/80358email1406727227.txt");
$parsed = getTextBetweenTags('td', $email);
$trimmed_array=array_map('trim',$parsed);
function getTextBetweenTags($tag, $html, $strict=0)
{
//a new dom object
$dom = new domDocument;
//load the html into the object
if($strict==1)
{
$dom->loadXML($html);
}
else
{
$dom->loadHTML($html);
}
// discard white space
$dom->preserveWhiteSpace = false;
// the tag by its tag name
$content = $dom->getElementsByTagname($tag);
// the array to return
$out = array();
foreach ($content as $item)
{
// add node value to the out array
$out[] = $item->nodeValue
}
// return the results
return $out;
}
//connect to drupal
define( 'DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT'] );
$base_url = 'http://' . $_SERVER['HTTP_HOST'];
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap( DRUPAL_BOOTSTRAP_FULL );
//create new node
$node = new stdClass();
$node->type = "Task";
node_object_prepare($node);
$node->title = $trimmed_array[0];
$node->language = 'en';
$node->status = 1;
$node->uid = 1; // UID of the author of the node; or use $node->name
$node->field_num['und'][0]['value'] =$trimmed_array[1];
$node->field_status['und'][0]['tid'] = 1 ;
...
node_save($node);
I manually execute the code above, it works, it takes .txt file, parses it, saves table cell values in array, connects to drupal, and creates a new node of type "task", but the problem starts when i change
line
$email = file_get_contents("emails/80358email1406727227.txt");
to line
$email = file_get_contents("php://stdin");
so when i send email, it gets piped to script, and it doesnt create a new node.
Im stuck here, any thoughts?
Why script can do the job when opening a .txt file, but does nothing when reads from stdin?

Create external XML file on page load

Basically I've set up a WPAlchemy metabox for the custom post type 'dealer' and I want to generate an XML file that contains formatted meta data from all of the dealer posts so that the data can be used for markers on a google map. Here's what I have in my functions.php file so far based off of Write to XML file using fopen in Wordpress
<?php function markers_xml() {
if ($_POST['post_type'] == 'es_dealer') {
$xml = new SimpleXMLElement('<xml/>');
$markers = get_posts('post_type=es_dealer&posts_per_page=-1');
$xml->addChild('markers');
foreach($markers as $i=>$marker) {
$name = get_the_title($marker->ID);
$lat = get_post_meta($marker->ID, 'lat', true);
$lng = get_post_meta($marker->ID, 'long', true);
$xml->markers->addChild('marker');
$xml->markers->marker[$i]->addAttribute('name', $name);
$xml->markers->marker[$i]->addAttribute('lat', $lat);
$xml->markers->marker[$i]->addAttribute('lng', $lng);
}
$file = 'http://encode-design.com/wp-content/uploads/test.xml';
$open = fopen($file, 'w') or die ("File cannot be opened.");
fwrite($open, $xml->asXML());
fclose($open);
}
}
add_action( 'save_post', 'markers_xml' ); ?>
When I save a dealer post I don't get a message saying 'File cannot be opened.' but there are no changes to the xml file either. I've set the xml file and the uploads folder permissions to 777 and fopen is enabled on my server. What am I missing? Any help would be much appreciated!
Add this code to check whether writing to the file is successful.
if(!fwrite($open, $xml->asXML()))
{
echo 'error';
}
else
{
echo 'success';
}
I switched to file_put_contents() instead of fopen, fwrite, and fclose and it did the trick! Also simplified my file path.
<?php
$xml = new SimpleXMLElement('<xml/>');
$markers = get_posts('post_type=es_dealer&posts_per_page=-1');
$xml->addChild('markers');
foreach($markers as $i=>$marker) {
global $dealer_mb;
$meta = $dealer_mb->the_meta($marker->ID);
$name = get_the_title($marker->ID);
$lat = $meta['lat'];
$lng = $meta['long'];
$xml->markers->addChild('marker');
$xml->markers->marker[$i]->addAttribute('name', $name);
$xml->markers->marker[$i]->addAttribute('lat', $lat);
$xml->markers->marker[$i]->addAttribute('lng', $lng);
}
$file = 'testing.xml';
$current = $xml->asXML();
file_put_contents($file,$current);
?>

how to customize text name on php when using fopen comman

how can i customize the text name for the output on my fopen?
i tried using
$file = $Aname .'.txt';
but it won't output correctly, and also after creating the text file return to the page
and prompt the user regarding the creation of the file .
<?php
$saving = $_REQUEST['saving'];
if ($saving == 1){
$Aname = $_POST['Aname'];
$name = $_POST['name'];
$last = $_POST['last'];
$mob = $_POST['mob'];
$ext = $_POST['ext'];
$email = $_POST['email'];
$add = $_POST['add'];
$com = $_POST['com'];
$day = $_POST['day'];
$text = $_POST['text'];
$date = date("M j, Y ");
$data = "Date Sent: {$date}\n\nName: {$name} {$last}\nPhone : {$mob} ext: {$ext}\nCompany: {$com}\nAddress : {$add}\nE-mail : {$email}\nDay : {$day}\n\nNote :
\n{$text}\n---------------------------------------\n";
$file = $Aname.'.txt';
$fp = fopen($file, "a") or die("Couldn't open $file for writing!");
fwrite($fp, $data) or die("Couldn't write values to file!");
fclose($fp);
}
?>
and also instead of relocating the user to another page to give this error
die("Couldn't write values to file!");
just pop up an alert on the page.
Make sure that $_POST['Aname'] is actually populated (maybe it is coming from $_GET?).
Do note by the way that you have opened a rather big security issue here by using unsanitized data to write to disk. Potentially people could overwrite any file on your disk with PHP code and then execute that.
Try using file_put_contents(). It replaces the whole fopen, fwrite, fclose headache.
http://php.net/manual/en/function.file-put-contents.php
<?php
$saving = $_REQUEST['saving'];
if ($saving == 1){
$Aname = $_POST['Aname'];
$name = $_POST['name'];
$last = $_POST['last'];
$mob = $_POST['mob'];
$ext = $_POST['ext'];
$email = $_POST['email'];
$add = $_POST['add'];
$com = $_POST['com'];
$day = $_POST['day'];
$text = $_POST['text'];
$date = date("M j, Y ");
$data = "Date Sent: {$date}\n\nName: {$name} {$last}\nPhone : {$mob} ext: {$ext}\nCompany: {$com}\nAddress : {$add}\nE-mail : {$email}\nDay : {$day}\n\nNote :
\n{$text}\n---------------------------------------\n";
$file = $Aname.'.txt';
file_put_contents ( $file, $data );
}
?>
You should use an absolute path for the $filename parameter of fopen, so replace your following line:
$file = $Aname.'.txt';
for this one:
$file = dirname($_SERVER["SCRIPT_FILENAME"]) . '/' . $Aname.'.txt';
The above assumes your web server runs linux, if it's a windows one, you have to escape any backslashes, like fopen("c:\\my\\document_root\\myfile.txt", "a");

Problem editing word file in PHP

So I need to edit some text in a Word document. I created a Word document and saved it as XML. It is saved correctly (I can open the XML file in MS Word and it looks exactly like the docx original).
So then I use PHP DOM to edit some text in the file (just two lines) (EDIT - bellow is already fixed working version):
<?php
$firstName = 'Richard';
$lastName = 'Knop';
$xml = file_get_contents('template.xml');
$doc = new DOMDocument();
$doc->loadXML($xml);
$doc->preserveWhiteSpace = false;
$wts = $doc->getElementsByTagNameNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 't');
$c1 = 0; $c2 = 0;
foreach ($wts as $wt) {
if (1 === $c1) {
$wt->nodeValue .= ' ' . $firstName;
$c1++;
}
if (1 === $c2) {
$wt->nodeValue .= ' ' . $lastName;
$c2++;
}
if ('First Name' === substr($wt->nodeValue, 0, 10)) {
$c1++;
}
if ('Last Name' === substr($wt->nodeValue, 0, 9)) {
$c2++;
}
}
$xml = str_replace("\n", "\r\n", $xml);
$fp = fopen('final-xml.xml', 'w');
fwrite($fp, $xml);
fclose($fp);
This gets executed properly (no errors). These two lines:
<w:t>First Name:</w:t>
<w:t>Last Name:</w:t>
Get replaced with these:
<w:t>First Name: Richard</w:t>
<w:t>Last Name: Knop</w:t>
However, when I try to open the final-xml.xml file in MS Word, it doesn't open (Word freezes). Any suggestions.
EDIT:
I tried using levenstein():
$xml = file_get_contents('template.xml');
$xml2 = file_get_contents('final-xml.xml');
$str = str_split($xml, 255);
$str2 = str_split($xml2, 255);
$i = 0;
foreach ($str as $s) {
$dist = levenshtein($s, $str2[$i]);
if (0 <> $dist) {
echo $dist, '<br />';
}
$i++;
}
Which outputted nothing.
Which is weird. When I open the final-xml.xml file in notepad, I can clearly see that those two lines have changed.
EDIT2:
Here is the template.xml file: http://uploading.com/files/61b2922b/template.xml/
This is a problem related to DOS vs UNIX line endings. Word 2007 does not tolerate a \n line ending, it requires \r\n whereas Word 2010 is more tolerant and accepts both versions.
To fix the problem make sure that you replace all UNIX line breaks with DOS ones before saving the output file:
$xml = str_replace("\n", "\r\n", $xml);
Full sample:
<?php
$firstName = 'Richard';
$lastName = 'Knop';
$xml = file_get_contents('template.xml');
$doc = new DOMDocument();
$doc->loadXML($xml);
$doc->preserveWhiteSpace = false;
$wts = $doc->getElementsByTagNameNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 't');
foreach ($wts as $wt) {
echo $wt->nodeValue;
if ('First Name:' === $wt->nodeValue) {
$wt->nodeValue = 'First Name: ' . $firstName;
}
if ('Last Name:' === substr($wt->nodeValue, 0, 10)) {
$wt->nodeValue = 'Last Name: ' . $lastName;
}
}
$xml = $doc->saveXML();
// Replace UNIX with DOS line endings
$xml = str_replace("\n", "\r\n", $xml);
$fp = fopen('final-xml.xml', 'w');
fwrite($fp, $xml);
fclose($fp);
?>
XML Word files have certain checksums stored near the top of the dom (to my recollection). You may have to change these, such as the size, or general checksum itself.
I know this was my problem when I was (dumb) enough to make an HTML file in word and save it, it has thousands of useless things in it that only served to make editing worse.

Categories