Jump to content

Append XML file with php


Texan78
Go to solution Solved by Texan78,

Recommended Posts

I have a php script that creates an XML file with data from a HTML form. It works great and the XML file is created and the form writes data to it. I am having a hard time appending data to the XML file though. Every time I submit new data from the form to the XML file it just overwrites the last one instead of just adding that data to it.

 

Here is the php script I am using to create and write the XML file from the form.

<?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('timestamp', date("D M jS g:i a",time()));
$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 output

 

http://www.mesquiteweather.net/xml/test2.xml

 

HTML Form in case anyways wants to see the behavior after new data is submitted.

 

http://www.mesquiteweather.net/wxmesqLSR-report.php

 

-Thanks!

Link to comment
Share on other sites

$str = '<?xml version="1.0" encoding="UTF-8"?><entrys></entrys>';
$xml = simplexml_load_string($str);
That's the part where $xml starts from scratch. It should first try to find a test2.xml file and use that, and only if that's not possible should it use the empty XML string.

 

$xml->reports = "";
That will (presumably) clear out the node. Don't do that. If you need it, which you do, then it should be declared in that initial XML as

<?xml version="1.0" encoding="UTF-8"?><entrys><reports /></entrys>
Also, "entries".

 

 

Have you considered what will happen if two people submit data at the same time? One of them will lose their changes.

Link to comment
Share on other sites

I am not sure I follow you. The script works great and does what I need it to do except I can only add one entry at a time. If a new entry is submitted from the form it just overwrites the current entry. It doesn't add the entry to the existing entries.

 

Without this....

$xml->reports = "";

It won't add any entries to the XML from the form.

 

I have since change it to this which works too.

$reports = $xml->addChild('reports');
$reports->addChild('timestamp', date("D M jS g:i a",time()));
$reports->addChild('fname', $fname);
$reports->addChild('lname', $lname);
$reports->addChild('location', $location);
$reports->addChild('report', $report);
$reports->addChild('description', $description);
Link to comment
Share on other sites

  • Solution

Ok well I have kept plugging away and I have a working script that allows me to add entries from the submission form without it overwriting the current one. Only issue I am having is in order for it to work there already has to be an existing entry.

 

So at all times there has to be something in there in order to submit to it. That won't work for me because if there isn't a report I have a table that displays that there is no reports. In order for that message to display the XML file needs to be empty but it can't be empty otherwise the form won't submit to it. So that is the pickle I am in now.

 

I need it to where I don't always have to have a entry in there like this.

<entry>
−
<reports>
<timestamp>Fri May 31st 11:50 pm</timestamp>
<fname>Mesquite</fname>
<lname>Weather</lname>
<location>Vanston Park</location>
<report>POWER OUTAGE</report>
<description>Oops I did it again!</description>
</reports>
</entry>

I need this instead if there is no entry and have the ability to submit a new entry without there being a current entry in the XML file.

<entry>

This is the current working script that I have right now.

<?php

if (isset($_POST['lsr-submit']))
    {
        header('Location: http://www.mesquiteweather.net/wxmesqLSR.php');
    }

$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('mesquite.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("D M jS 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('entry')->item(0)->appendChild($newItem);

$xml->save('mesquite.xml');

?>

Any suggestions or ideas?

Edited by Texan78
Link to comment
Share on other sites

I need it to where I don't always have to have a entry in there like this.

 

 

Sorry... what?

 

Yes

 

Great answer, care to share why?

 

If you NEED to use an XML file I suggest you do the following:

  1. Break your problem down into small problems, i.e. I need to create a file if it doesn't exist and append to one if it does.
  2. Tackle each problem individually, one-at-a-time.
  3. Comment your code so you, and others, know whats going on.
  4. Change "reports" to "report" as it contains report information not many reports.
  5. Define a Document Type Definition (DTD) to create a fully qualified XML document.

Once you've broken the larger problem down into smaller ones you will, hopefully, find its actually a really easy task.

 

Let me get you started

// Does the file exist?
if(file_exists($file)) {
    // Yes, lets get its contents
    $xml = file_get_contents($file);
} else {
    // No, lets set up a default
    $xml = "<entries></entries>"; //Should also contain the DTD and the XML definition. Perhaps have a default XML file.
}


// Lets load the XML into a DOMDocument object...
$dom = DOMDocument::loadXML($xml);


// Now lets append entries. This will be the same regardless of whether or not the file already exists.
Edited by cpd
Link to comment
Share on other sites

 

Sorry... what?

 

 

Great answer, care to share why?

 

If you NEED to use an XML file I suggest you do the following:

  1. Break your problem down into small problems, i.e. I need to create a file if it doesn't exist and append to one if it does.
  2. Tackle each problem individually, one-at-a-time.
  3. Comment your code so you, and others, know whats going on.
  4. Change "reports" to "report" as it contains report information not many reports.
  5. Define a Document Type Definition (DTD) to create a fully qualified XML document.

Once you've broken the larger problem down into smaller ones you will, hopefully, find its actually a really easy task.

 

Let me get you started

// Does the file exist?
if(file_exists($file)) {
    // Yes, lets get its contents
    $xml = file_get_contents($file);
} else {
    // No, lets set up a default
    $xml = "<entries></entries>"; //Should also contain the DTD and the XML definition. Perhaps have a default XML file.
}


// Lets load the XML into a DOMDocument object...
$dom = DOMDocument::loadXML($xml);


// Now lets append entries. This will be the same regardless of whether or not the file already exists.

 

 

Please read this again carefully

 

http://forums.phpfreaks.com/topic/278650-append-xml-file-with-php/?do=findComment&comment=1433506

Link to comment
Share on other sites

Read it again, my previous answer still stands. I took your two posts combined and wrote the following script, tested it, and confirmed it works as you want it too; unless I've completely misinterpreted your OP.

 

$file = "entries.xml";


// Does the file exist?
if(file_exists($file)) {
    $xml = file_get_contents($file);
} else {
    $xml = file_get_contents("entries_default.xml");
}


// Looad the XML in
$dom = new DOMDocument("1.0", "UTF-8");
$dom->loadXML($xml);
$root = $dom->getElementsByTagName("entries")->item(0);


// Create the report element
$report = $dom->createElement("report");

// Add the reports children.
$report->appendChild($dom->createElement("timestamp", gmdate("Y-m-d H:i:s")));
$report->appendChild($dom->createElement("fname", "First name"));
$report->appendChild($dom->createElement("lname", "Last name"));
$report->appendChild($dom->createElement("location", "Location"));
$report->appendChild($dom->createElement("type", "Report type"));
$report->appendChild($dom->createElement("description", "This is my description"));


// Append the report
$root->appendChild($report);


// Save as XML
$dom->save($file);

 

entries_default.xml

<?xml version="1.0" encoding="UTF-8"?>
<entries>
    
</entries>

 

Written in 5-10 minutes at 2:30am. Like I said, the problem is easy to solve if you break it down.

 

Take the advice next time.

Edited by cpd
Link to comment
Share on other sites

 

unless I've completely misinterpreted your OP.

 

 

I think you may have. That's why I said read this post which is an update to my OP.

 

http://forums.phpfreaks.com/topic/278650-append-xml-file-with-php/?do=findComment&comment=1433506

 

 

Like I said this script WORKS exactly like I need it to BUT, there has to be at least ONE entry in the XML or the HTML form won't submit. I need to be able to submit to the XML when it's empty.

<?php

if (isset($_POST['lsr-submit']))
    {
        header('Location: http://www.mesquiteweather.net/wxmesqLSR.php');
    }

$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('mesquite.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("D M jS 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('entry')->item(0)->appendChild($newItem);

$xml->save('mesquite.xml');

?>

ALSO when it's empty it will still show the elements but they are empty. When that happens it shows an empty table instead of my "No reports at this time" table from my script that I use to display the data from the XML file which you can see from the links in my OP. Which works because I have tested it BUT, it won't show unless the XML is empty. It can't be empty or the form won't submit to the XML. That's the issue I am having right now.

 

Thanks for the help but, please all the updates carefully as my OP has been solved with the exception of the small issue I have listed. I don't want to have to rewrite my entire working code if I don't have to.

 

http://forums.phpfreaks.com/topic/278650-append-xml-file-with-php/?do=findComment&comment=1433506

Edited by Texan78
Link to comment
Share on other sites

You never said you needed to populate the form using data from the XML file. The problem you specified was that you had an issue appending to an XML file.

 

Does this mean you want to populate the form with the first entry or the last entry? 

Do you want to overwrite what's already in the XML file or append to it as they are two completely different tasks?

Link to comment
Share on other sites

You never said you needed to populate the form using data from the XML file. The problem you specified was that you had an issue appending to an XML file.

 

Does this mean you want to populate the form with the first entry or the last entry? 

Do you want to overwrite what's already in the XML file or append to it as they are two completely different tasks?

 

 

Please go read the first paragraph in my OP carefully.

 

Then read the UPDATE to my OP carefully from this post.

 

http://forums.phpfreaks.com/topic/278650-append-xml-file-with-php/?do=findComment&comment=1433506

 

And you're right. I never said "I needed to populate the form using data from the XML file". I am using a form which I posted a link to from my OP to populate date TO the XML file as I stated in my first sentence in my OP. Had you read my posts carefully and visited the links I posted to the example you would have seen this and how it's suppose to work. The problem I WAS having is I couldn't append data FROM the form TO the XML file. Every time I would make a new submission it would overwrite the existing entry instead of appending the new submission TO the XML file. I have since fixed that issue.

 

Problem now is that there has to be at least one entry in the XML file or the form won't submit TO the XML file. I need to be able to submit FROM the form TO the XML when it is empty but I am unable to do that as it won't submit TO the XML file unless there is at least one entry. Which in turn if there is no submissions in weeks it will show at least one outdated report in the table on this page. So if there is no recent reports in X amount of time the XML file needs to be empty but, that is different issue I will sort out later but in order to do that I have to sort this out first.

 

http://www.mesquiteweather.net/wxmesqLSR.php

 

So I need to be able to submit from the form TO the XML file when it's empty and when it's empty it needs to show nothing in the file. As it stands now if it is empty it just shows empty elements. Which causes two other issues, one being not able to submit FROM the form TO the XML file.

Edited by Texan78
Link to comment
Share on other sites

I'm either seriously missing something, or have interpreted your posts correctly and you're failing to match the dots up.

 

<?php




$file = "entries.xml";


// Does the file exist?
if(file_exists($file)) {
    $xml = file_get_contents($file);
} else {
    $xml = file_get_contents("entries_default.xml");
}


// Looad the XML in
$dom = new DOMDocument("1.0", "UTF-8");
$dom->loadXML($xml);


// Was the form submitted?
if(isset($_POST['xml_append'])) {
    // Get the root node
    $root = $dom->getElementsByTagName("entries")->item(0);
    
    // Unset the submit button post data
    unset($_POST['xml_append']);
    
    // Create variables for each $_POST element
    extract($_POST);


    // Create the report element
    $report = $dom->createElement("report");
    $report->appendChild($dom->createElement("timestamp", gmdate("Y-m-d H:i:s")));
    $report->appendChild($dom->createElement("fname", $fname));
    $report->appendChild($dom->createElement("lname", $lname));
    $report->appendChild($dom->createElement("location", $location));
    $report->appendChild($dom->createElement("type", $type));
    $report->appendChild($dom->createElement("description", $description));


    // Append the report
    $root->appendChild($report);


    // Save as XML
    $dom->save("entries.xml");
}


// Get the last piece of data saved
$reports = $dom->getElementsByTagName("report");
if($reports->length > 0) {
    $data = array();
    $children = $reports->item(($reports->length-1))->childNodes;
    foreach($children as $child) {
        $data[$child->nodeName] = $child->textContent;
    }
}


?>
<html>
    <body>
        <form method="post">
            <fieldset style="display: inline-block;">
                <label>Fname</label><input type="text" name="fname" value="<?=(isset($data) ? $data["fname"] : "");?>" /><br />
                <label>Lname</label><input type="text" name="lname" value="<?=(isset($data) ? $data["lname"] : "");?>" /><br />
                <label>Location</label><input type="text" name="location" value="<?=(isset($data) ? $data["location"] : "");?>" /><br />
                <label>Type</label><input type="text" name="type" value="<?=(isset($data) ? $data["type"] : "");?>" /><br />
                <label>Description</label><input type="text" name="description" value="<?=(isset($data) ? $data["description"] : "");?>" /><br />
                <input type="submit" name="xml_append" value="Save" />
            </fieldset>
        </form>
    </body>
</html>

Default XML file is as before. 

 

This uses a form to write data via PHP to an XML file. It does not submit a form to an XML file, that's just silly. If there are no entries, it still writes to the file. If there are entries, it still writes to the file. It also attempts to get the last entry and populates the fields with the data.

 

I'm still standing by my original comments. And once again this was modified in less than 5 minutes.

Edited by cpd
Link to comment
Share on other sites

Are you not reading anything I am posting. It is clear as day, I don't know how much clearer I can make it. Have you read everything and visited the links I posted to demo to see how it's setup?

 

Are you testing this code because it doesn't work. Just to amuse you I tried your code. It does the EXACT same thing as the code I have now does. So I guess I will waste some more time explaining this.

 

I used YOUR code which works great for submit TO THE XML file FROM the form IF THERE IS AN EXISTING entry like my original code worked so this is what the XML file looked like with an existing entry.....

<entry>
−
<reports>
<timestamp>Fri May 31st 11:50 pm</timestamp>
<fname>Mesquite</fname>
<lname>Weather</lname>
<location>Vanston Park</location>
<report>POWER OUTAGE</report>
<description>Oops I did it again!</description>
</reports>
</entry>

Then it would append the XML file...

 

BUT... Once you completely delete the contents of the XML file NOT the actual file like so....

 

http://www.mesquiteweather.net/xml/test3.xml

 

Then you are unable to submit TO the XML file FROM the form.

 

Go ahead and try it.

 

http://www.mesquiteweather.net/wxmesqLSR-report.php

 

Once you submit it, it will take you to a page where it should be displayed below the map and it isn't working which works great IF there is an existing entry. Then check the XML file after you have submitted and you will see nothing was wrote to it.

 

It will only submit OR append if there is an existing entry in the XML file. As you can see the XML file DOES exist. Your code did exactly what my previous code was doing which WORKS GREAT if there is an existing entry but, once the XML file is empty then no.

 

I appreciate your help but please read my posts carefully because had you, you would have known this already and both yours and my time wouldn't have been wasted.

 

-Thanks!

Link to comment
Share on other sites

So figure out why.

 

At first glance I'd say the problem is likely to be that you're looking for a root node, and one won't exist. So add some logic to capture that event, and create the needed node.

Link to comment
Share on other sites

So figure out why.

 

Uh, I think that is what I am trying to do....

 

So add some logic to capture that event, and create the needed node.

 

I guess you didn't read all of this or see my code or you have no idea ether or you will see I had tried that in my OP.

 

But thanks for stating the obvious.

Link to comment
Share on other sites

So, in a single sentence:

 

"When the XML file exists but has no contents, i.e. does not contain an 'entries' element, I can't write to it".

 

And once again, I still stand by my original comments regarding breaking the problem down into smaller ones and this being a simple problem.



<?php


$file = "entries.xml";
$default = "entries_default.xml";




// Does the file exist? Does it contain data?
if(!file_exists($file) || ($xml = file_get_contents($file)) == "") {
    $xml = file_get_contents($default);
}


// Looad the XML in
$dom = new DOMDocument("1.0", "UTF-8");




$dom->loadXML($xml);




// Was the form submitted?
if(isset($_POST['xml_append'])) {
    // Get the root node
    $root = $dom->getElementsByTagName("entries");
    
    // Was the root node found? No, so create the file again using the default
    if($root->length == 0) {
        $dom->loadXML(file_get_contents($default));
    }
    
    $root = $dom->getElementsByTagName("entries")->item(0);
    
    // Unset the submit button post data
    unset($_POST['xml_append']);
    
    // Create variables for each $_POST element
    extract($_POST);




    // Create the report element
    $report = $dom->createElement("report");
    $report->appendChild($dom->createElement("timestamp", gmdate("Y-m-d H:i:s")));
    $report->appendChild($dom->createElement("fname", $fname));
    $report->appendChild($dom->createElement("lname", $lname));
    $report->appendChild($dom->createElement("location", $location));
    $report->appendChild($dom->createElement("type", $type));
    $report->appendChild($dom->createElement("description", $description));




    // Append the report
    $root->appendChild($report);




    // Save as XML
    $dom->save("entries.xml");
}




// Get the last piece of data saved
$reports = $dom->getElementsByTagName("report");
if($reports->length > 0) {
    $data = array();
    $children = $reports->item(($reports->length-1))->childNodes;
    foreach($children as $child) {
        $data[$child->nodeName] = $child->textContent;
    }
}




?>
<html>
    <body>
        <form method="post">
            <fieldset style="display: inline-block;">
                <label>Fname</label><input type="text" name="fname" value="<?=(isset($data) ? $data["fname"] : "");?>" /><br />
                <label>Lname</label><input type="text" name="lname" value="<?=(isset($data) ? $data["lname"] : "");?>" /><br />
                <label>Location</label><input type="text" name="location" value="<?=(isset($data) ? $data["location"] : "");?>" /><br />
                <label>Type</label><input type="text" name="type" value="<?=(isset($data) ? $data["type"] : "");?>" /><br />
                <label>Description</label><input type="text" name="description" value="<?=(isset($data) ? $data["description"] : "");?>" /><br />
                <input type="submit" name="xml_append" value="Save" />
            </fieldset>
        </form>
    </body>
</html>

A less than 5 minute edit to do what you want. This now performs two additional checks: 1) Checks if anything is in the XML file and if not uses the default; 2) Checks for an "entries" node and if it doesn't exist, uses the default.

Edited by cpd
Link to comment
Share on other sites

I got it working correctly with my code without having to completely rewrite it with two simple edits and without having to go back to tweek it to work with my html form and display script.

 

All I had to do was replace this....

$str = '<?xml version="1.0" encoding="UTF-8"?><entrys></entrys>';
$xml = simplexml_load_string($str);

With this and works great and is simple and not complex without a complete code overhaul.

$str = '<?xml version="1.0" encoding="UTF-8"?><entrys></entrys>';
$xml = false;if(file_exists('mesquite.xml'))
$xml = simplexml_load_file('mesquite.xml'); if(!$xml) $xml = simplexml_load_string('<entrys/>');

Like I said, had you read my OP and then update you would have noticed it didn't need a complete overhaul. Thanks though!

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.