Jump to content

Deleting XML entries after certain amount of time


Texan78
Go to solution Solved by cpd,

Recommended Posts

I have done a search but I can't really find anything related to what I am needing. I am not sure if I am searching for it correctly or not. I have an XML file that is created via PHP and populated with data from a form. What I am trying to do is delete certain entries in that XML file after X amount of time. Is there an easy way to do this or can it even be done at all. I was thinking of some php script that was run by a CRON to check the XML file and delete certain entries by the timestamp after X amount of time. Can someone provide some suggestions or get me pointed in the right direction?

 

-Thanks!

 

Link to comment
Share on other sites

I can't edit my original post so I will just add it here. This is the code I have come up with but a little stuck. I was thinking of a php script that is run by a CRON that will load the XML and look for any entries older than 12 hours and remove them then resave the XML. Where I am stuck is I am not sure how set it to check for entries older than 12 hours. Am I on the right track? Any suggestions?

<?php

$doc = new DOMDocument; 
$doc->load('mesquite.xml');

$thedocument = $doc->documentElement;

//this gives you a list of the reports
$list = $thedocument->getElementsByTagName('reports');

//figure out which ones you want -- assign it to a variable (ie: $nodeToRemove )
$nodeToRemove = null;
foreach ($list as $domElement){
  $attrValue = $domElement->getAttribute('timestamp');
  if ($attrValue == 'VALUEYOUCAREABOUT') {
    $nodeToRemove = $domElement; //will only remember last one- but this is just an example 
  }
}

//Now remove it.
if ($nodeToRemove != null)
$thedocument->removeChild($nodeToRemove);

echo $doc->saveXML(); 
?>

Here is an example of the XML

<entrys>
−
<reports>
<timestamp>Mon Jun 3rd 7:34 am</timestamp>
<fname>Unknown</fname>
<lname/>
<location/>
<report>WIND DAMAGE</report>
<description>Enter report description</description>
</reports>
−
<reports>
<timestamp>Tue Jun 4th 12:02 pm</timestamp>
<name/>
<location>Mesquite</location>
<report>GENERAL</report>
<description>Test of the form input. </description>
</reports>
</entrys>
Edited by Texan78
Link to comment
Share on other sites

How often is the XML updated? Can you modify whatever reads it? Because you might be able to make the reader skip over old entries when displaying the contents, then make whatever updates it also remove old entries. No cron required.

Link to comment
Share on other sites

How often is the XML updated? Can you modify whatever reads it? Because you might be able to make the reader skip over old entries when displaying the contents, then make whatever updates it also remove old entries. No cron required.

 

The XML is updated manually by persons who are submitting a storm report from a form on one of the pages. So there is really only data when there is a storm. Which is why I was wanting to delete it after certain amount of time so there isn't old reports just sitting there for weeks if there is no storms.

 

I like that idea of no cron. It's not a big deal having to set up one though. I just figured having a separate file to remove entries then call it with a cron would be easier to keep the code separated. I am not sure how easy that would be to implement into the code that displays the data.

 

This is what I have come up with so far but it's not removing anything. It should remove it all of it because it's all over an hour but it doesn't.

<?php

$doc = new DOMDocument;
$doc->load('mesquite.xml');

$thedocument = $doc->documentElement;

//this gives you a list of the reports
$list = $thedocument->getElementsByTagName('reports');

//figure out which ones you want -- assign it to a variable (ie: $nodeToRemove )
$reports = null;
foreach ($list as $domElement){
 $timestamp = strtotime($domElement->getAttribute('timestamp'));
if ($timestamp < strtotime('now - 1 hour')) {    $reports = $domElement;

//Now remove it.
if ($reports != null)
$thedocument->removeChild($reports);

  }
}

echo $doc->saveXML();
?>

When I run it this is what it's echo'ing

 

http://www.mesquiteweather.net/xml/update.php

 

Which seems to be adding entries.

 

Here is the raw XML

 

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

Link to comment
Share on other sites

2 issues: 

$timestamp = strtotime($domElement->getAttribute('timestamp'));

1) Timestamp is an element in your XML document, not an attribute. 

 

2) Are you sure the date/time format you've stored in the XML is a valid date/time format as per the documentation http://uk1.php.net/manual/en/datetime.formats.php? It doesn't look like any of the valid ones to me, could be wrong though. Best thing to do is echo it out and see if it worked.

Edited by cpd
Link to comment
Share on other sites

When I run it this is what it's echo'ing

 

http://www.mesquiteweather.net/xml/update.php

 

 

Timestamp is an element in your XML document, not an attribute

 

True, but if you look at that line carefully it is "$domElement->getAttribute" and "$reports = $domElement;" which means it should be looking for the element "timestamp" then get the attribute of timestamp being the date/time.

 

This is what's in the script that creates the data for the entries.

$reports->addChild('timestamp', date("D M jS g:i a",time()));
Edited by Texan78
Link to comment
Share on other sites

Afraid not. Its actually looking for an attribute called "timstamp" in the "reports" nodes.

 

So what its expecting is

<reports timestamp="[some timestamp]">
...
</reports>

Like I said before, "timestamp" is an element, not an attribute. No matter which node you try to select it from using the $node->getAttribute($name) method, it'll never get it, EVER, because its not an attribute.

 

If you want the timestamp of the first "reports" node you need:

$timestamp = $dom->getElementsByTagName("reports")->item(0)->getElementsByTagName("timestamp")->item(0)->textContent;
Edited by cpd
Link to comment
Share on other sites

Reviewing that you can just do $root->getElementsByTagName("timestamp")->item(0)->textContent; but in your scenario you need the reports node as well.

Edited by cpd
Link to comment
Share on other sites

I hear what you're saying and that makes sense. How it's suppose to work is it is suppose to check the timestamp. If it is X amount from the time now it is suppose to remove that report. This code is code I have found after doing extensive searching. I really haven't been able to find anything solid associated with what I need. So I have just been trying to piece together code from searches.

 

That is what the line is code is suppose to do. It is just suppose to check the time as a qualifier.

$timestamp = strtotime($domElement->getAttribute('timestamp'));
if ($timestamp < strtotime('now - 1 hour')) {    $reports = $domElement;

When I echo the script it shows all the entries it should remove. It is just not removing them.

 

http://www.mesquiteweather.net/xml/update.php

<?php

$doc = new DOMDocument;
$doc->load('mesquite.xml');

$thedocument = $doc->documentElement;

//this gives you a list of the reports
$list = $thedocument->getElementsByTagName('reports');

//figure out which ones you want -- assign it to a variable (ie: $nodeToRemove )
$reports = null;
foreach ($list as $domElement){
 $timestamp = strtotime($domElement->getAttribute('timestamp'));
if ($timestamp < strtotime('now - 1 hour')) {    $reports = $domElement;

//Now remove it.
if ($reports != null)
$thedocument->removeChild($reports);

  }
}

echo $doc->saveXML();
?>
Edited by Texan78
Link to comment
Share on other sites

  • Solution

You're still not hearing me or thinking logically about this.

 

$report->getAttribute("timestamp") will look for the "timestamp" attribute in each report node:

<reports timestamp="[some timestamp]">
...
</reports>

You want to get an element that's that's a child node of the "reports" tag and as such should grab it the same way as you would get the reports using $report->getElementByTagName("timestamp"):

$reports = $root->getElementByTagName("reports");
foreach($reports as $report) {
   $timestamp = $report->getElementByTagName("timestamp")->item(0);
   // Code omitted
}

This now looks for the timestamp using the XML structure you have.

 

Because I'm feeling nice, I wrote this script in 10 minutes by applying logical thought and reading the documentation. It removes the "reports" that are older than 1 hour:

 

// Load the document
$doc = new DOMDocument();
$doc->load('test.xml');


// Get the root node and timestamps
$root = $doc->documentElement;
$timestamps = $root->getElementsByTagName("timestamp");


// Define a variable for the current time
$currentTime = strtotime("-1 hour");


// Define an array to hold the nodes we want to remove
$remove = array();


// Cycle through each timestamp and determine if it was set more than 1 hour ago
// If so add it to our remove array
foreach($timestamps as $ts) {
    $time = strtotime($ts->textContent);
    if($time < $currentTime) {
        $remove[] = $ts->parentNode;
    }
}


// Remove all the nodes found
foreach($remove as $node) {
    $root->removeChild($node);
}


// Save the document
$doc->save("test.xml");

 

You'll notice I did it slightly differently than the way you were trying to do it. I just grabbed the timestamps and looped through them, when one is found that's older than 1 hour, it adds the parent node on to the remove array; the parent node being the "reports" node associated with that timestamp.

Edited by cpd
Link to comment
Share on other sites

You're still not hearing me or thinking logically about this.

 

Yes I do hear you as I clearly stated in my last post, first sentence, "I hear what you're saying and that makes sense". I was just trying to explain what I was trying to do so you would have better information and we were on the same page.

 

It appears to be working as when I run the script it removed all the entries. I am running a test so I will know more in an about 30 mins.

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.