перемещение указателя файла вверх на одну строку (php)? - PullRequest
3 голосов
/ 23 августа 2009

Я пытаюсь автоматизировать файл sitemap.xml на моем сайте, так как его содержание постоянно меняется. В настоящее время я открываю файл для добавления: fopen($file_name, 'a');, чтобы я мог добавить новый набор тегов. Однако я только что заметил, что весь файл карты сайта должен заканчиваться тегом, который означает, что каждый раз, когда я открываю файл, мне нужно добавлять текст не к концу файла, а к 1 строке от конца.

Так в принципе, как я могу переместить указатель файла вверх после открытия файла для добавления, чтобы я мог добиться этого? Спасибо.

Обновление: вот как выглядит карта сайта:

<?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>

поэтому, когда я добавляю, мне нужно добавить часть <url>..</url>, которая должна идти прямо перед закрывающим тегом </urlset>. У меня уже есть код, который может добавить XML в конец файла. Мне просто нужно выяснить, как добавить новую часть прямо перед закрывающим тегом.

Ответы [ 5 ]

7 голосов
/ 23 августа 2009

Используйте php fseek (), чтобы найти конец файла (найдите, используя filesize ()), затем выполните итерацию в обратном направлении на одну строку. прочитайте последнюю строку и сохраните ее временно. переписать последнюю строку с тем, что вы хотите вставить, а затем добавить временную строку, которую вы сохранили ранее.

Чтобы перебрать одну строку назад, используйте fseek в сочетании с fgetc ()

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

и теперь ваш внутренний указатель файла должен указывать на строку перед последней строкой. Конечно, вам придется иметь дело с угловыми случаями, когда ваш файл имеет только одну строку, но я дам вам разобраться в деталях;)

теперь сохраняем последнюю строку в переменной tmp

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

вставьте свою строку и добавьте последнюю строку в конец файла

fwrite($fhandle, $myLine);
fwrite($fhandle, $lastline);
3 голосов
/ 23 августа 2009

Не видя XML, о котором вы говорите, и не зная, что вы пытаетесь добавить (пожалуйста, предоставьте их для полного закодированного ответа), могу я предложить этот подход ...

  1. Загрузка всего файла с использованием синтаксического анализатора PHP XML (http://uk3.php.net/manual/en/ref.xml.php)
  2. Добавить новый элемент в XML
  3. Сохранение с использованием функций fopen () и fwrite () (в любом случае, я предполагаю, что вы делаете этот бит)

Как я уже сказал, не видя XML или какого-либо другого кода, очень трудно предоставить и ответить

1 голос
/ 22 ноября 2009

Добавление к ответу Чарльза Ма. Вы можете сохранить это в файле с именем sitemapper.php и вызвать этот файл с помощью запроса GET, хотя я бы посоветовал вам добавить больше защиты и flock (), если у вас могут быть одновременные записи.

Другая причина использовать это может быть, если вы используете PHP4, у которого нет 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);
    }
}
?>
0 голосов
/ 23 августа 2009

fseek ($ fp, -n, SEEK_END); но вы должны открыть файл как 'r +', а не как 'a'.

Обычно не очень хорошая идея обрабатывать XML; полагаться на точные байтовые позиции очень хрупко. Лучше было бы открыть файл в синтаксическом анализаторе XML, добавить нужные элементы, сериализовать его в новый файл и поменять их местами (чтобы ничто не читало XML в середине написанного вами).

На сайте, поддерживаемом базой данных, вы также можете рассмотреть возможность динамической генерации XML-карты вашего сайта с использованием самого PHP.

0 голосов
/ 23 августа 2009

Сохраните две версии файла: карту сайта и tmp без закрывающего тега. Если вы хотите расширить, сначала расширьте tmp; затем скопируйте его в карту сайта и добавьте туда закрывающий тег.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...