Move file pointer one line (php)?

I am trying to automate the sitemap.xml file on my site as the content is constantly changing. I am currently opening a file to add: fopen($file_name, 'a');

to add a new set of tags. However, I just noticed that the entire sitemap must end with a tag, which means that every time I open the file, I need to add text not to the end of the file, but to 1 line from the end.

So how can I move the file pointer after opening the file for append so that I can do this? Thank.

Update: This is what the sitemap looks like:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
    <url>
        <loc>...</loc>
        <lastmod>2009-08-23</lastmod>
        <changefreq>weekly</changefreq>
        <priority>0.8</priority>
    </url>
    </urlset>

      

so whenever I add I need to add the part <url>..</url>

that should go right before the closing tag </urlset>

. I already have some code that can add xml to the end of the file. I just need to figure out how to add the new part just before the closing tag.

+2


source to share


5 answers


Use php fseek () to search at the end of the file (find with filesize ()), then loop back one line. read the last line and save it temporarily. overwrite the last line with whatever you want to insert, then add the temp line you saved earlier.

To iterate backward one line, use fseek in combination with fgetc ()

$offset = filesize($fhandle) - 1;
fseek($fhandle, $offset--); //seek to the end of the line
while(fgetc($fhandle) != '\n') {
   fseek($fhandle, $offset--);
}

      

and now your internal file pointer should be pointing to the line before the last line. you'll have to deal with corner cases where you only have one line in your file, but I'll let you understand the details;)



now store the last line in the tmp variable

$lastline = fgets($fhandle);
fseek($fhandle, $offset); //go back to where the last line began

      

insert your line and add the last line to the end of the file

fwrite($fhandle, $myLine);
fwrite($fhandle, $lastline);

      

+6


source


Not seeing the XML you are talking about and not knowing what you are trying to add (please provide them for a complete coded answer), I can suggest this approach ...

  • Download the whole file using PHP XML Parser ( http://uk3.php.net/manual/en/ref.xml.php )
  • Add new element to XML
  • Save with the fopen () and fwrite () functions (I assume you are doing this bit anyway)


As I said, without seeing XML or some other code, it is very difficult to provide and answer

+3


source


Adding to Charles Ma's answer. You can store this in a file named sitemapper.php

and invoke that file with a GET request, although I would suggest you add some extra safety and flock () if you can have concurrent writes.

Another reason to use this would be if you are using PHP4 which does not have a SimpleXMLParser.

<?php
/*--------------------------------------------------------
==================
sitemapper.php 1.0
==================
Pass me a path to a page, and I will add it to your XML sitemap.

Paths are passed from root, as 
www.example.com/sitemapper.php?path=/test/index.html
for a page at http://www.example.com/test/index.html

This script is faster than parsing XML, for large sitemaps.
--------------------------------------------------------*/

if (isset($_GET[path])) {

    // Get the path to the new page to add to our sitemap.
    $fname = urldecode($_GET[path]);

    // Real path to files is different on some hosts.
    $current_path = realpath(dirname(__FILE__));

    if (!is_file("./sitemap.xml")){

        $xml = '';
        $xml =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"."\n";
        $xml .= "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">"."\n";
        $xml .= "</urlset>"."\n";

        $sitemap = fopen("./sitemap.xml", "x");             
        fwrite($sitemap, $xml); 
        fclose($sitemap);
    }

    // Write sitemap.xml entry for current file
    // This is a very old-school 'C' style of doing it.
    // The modern way would be to open the file in an XML parser, 
    // add the elements you want, serialise it to a new file 
    // and swap them over (so that nothing reads the XML in 
    // the middle of you writing it)
    //
    // However I expect this XML file to become *huge* shortly
    // So I am avoiding use of the PHP XML Parser.

    $date = date('Y-m-dTH:i:sP', time()); //Date in w3c format for XML sitemaps

    $xml = '';
    $xml .= "<url>"."\n";
    $xml .= "   <loc>http://". $_SERVER["HTTP_HOST"] . $fname . "</loc>"."\n";
    $xml .= "   <lastmod>" . $date . "</lastmod>"."\n";
    $xml .= "   <priority>0.50</priority>"."\n";
    $xml .= "   <changefreq>never</changefreq>"."\n";
    $xml .= "</url>"."\n";            

    if ($sitemap = @fopen("./sitemap.xml", "r+")) 
    {

        // seek to the end of the file, then iterate backwards one line. 
        // read the last line and store it temporarily. overwrite the 
        // last line with what you want to insert, then append the 
        // temporary line you stored previously.

        $offset = filesize("./sitemap.xml") - 1;

        fseek($sitemap, ($offset - 1)); //seek to before the last character in the file
        while( (($char = fgetc($sitemap)) !== "\n") && ($offset > -2000) && ($offset < 2000)) {
            // Go backwards, trying to find a line-break.
            // The offset range is just a sanity check if something goes wrong.
            $offset = $offset - 1;
            fseek($sitemap, $offset);
        }  

        $offset = $offset + 1; // Come to the beginning of the next line
        fseek($sitemap, $offset);
        $lastline = fgets($sitemap); // Copy the next line into a variable
        fseek($sitemap, $offset); //go back to where the last line began

        fwrite($sitemap, $xml); // add the current entry
        fwrite($sitemap, $lastline); // add the </urlset> line back.

        fclose($sitemap);
    }
}
?>

      

+1


source


Save two versions of the file: sitemap and tmp without an end tag. When you want to expand, first increase tmp one; then copy it to your sitemap and add a closing tag there.

0


source


fseek ($ fp, -n, SEEK_END); but you must open the file as' r + ', not' a ".

It is generally not recommended to process XML in this way; relying on exact byte positions is very fragile. Better would be to open the file in an XML parser, add the elements you want, serialize it to a new file, and swap it (so that nothing reads XML in the middle of writing).

On a database-backed site, you can also dynamically generate an XML Sitemap using PHP itself.

0


source







All Articles