使用php将数据附加到xml文件

问题描述

我是 xml 文件相关内容的新手。我遇到了一个问题。

我有一个 MysqL 查询,它获取了将近 5000 行的 url 数据(1 行包含 1 个 url)。 所以我已经实现了一个 cron,它通过分页MysqL 一次获取 1000 行。我需要对 url 进行一些验证,并且应该将有效的 url 附加到 xml 文件中。

这是我的代码

public function urlcheck()
    {
        $xFile = $this->base_path."sitemap/path/urls.xml";
        $page = 0;
        $cache_key = 'valid_urls';
        $page = $this->cache->redis->get($cache_key);
        if(!$page){
            $page=0;
        }

        $xFile = simplexml_load_file($xFile);

        $this->load->model('productnew/productnew_es6_m');
        $urls= $this->db->query("SELECT url FROM product_data where `active` = 1 limit ".$page.",1000")->result();

        $dom = new DOMDocument('1.0','UTF-8');
        $dom->formatOutput = true;      
        $root = $dom->createElement('urlset');
        $root->setAttribute('xsi:schemaLocation','http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
        $root->setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
        $root->setAttribute('xmlns','http://www.sitemaps.org/schemas/sitemap/0.9');
        $dom->appendChild($root);
        

        foreach($urls as $val)
        {   
            // validations here 
            $url = $dom->createElement('url');
            $root->appendChild($url);

            $lastmod = $dom->createElement('lastmod',date("Y-m-d"));
            $url->appendChild($lastmod);

            $page++;
        }

        $dom->saveXML();
        $dom->save($xFile) or die('XML Create Error');
        
        if(sizeof($urls) == 0){
            $page = 0;
        }
        print_r($page);
        $this->cache->redis->save($cache_key,$page,432000);
        // echo '<xmp>'. $dom->saveXML() .'</xmp>';
        // $dom->saveXML();
        // $dom->save($xFile) or die('XML Create Error');
        
    }

在我第一次执行 cron 后,1000 个 url 中的 300 个有效 url 被保存到 xml 文件中, 现在让我们说在我的第二个 cron 执行中,我有 1000 个有效网址中的 200 个。

我的预期结果是将这 200 个附加到现有的 xml 文件中,以便我的 xml 文件包含总共 500 个有效 url,并且 xml 文件应该在 5000 个 url 后刷新,如上所述。

但是每次执行 cron 后,旧的 url 数据将被替换为最新的一次。

我想知道如何在不覆盖 XML 的情况下保存 url 值。 提前致谢!

解决方法

根据上面的评论,您使用一个 api (SimpleXML) 打开文件,但使用 DOMDocument 保存一个新文档 - 从而覆盖以前的工作。如果没有 SimpleXML,也许您可​​以这样尝试 - 尽管它未经测试。

public function urlcheck(){
    
    $file=$this->base_path."sitemap/path/urls.xml";
    $cache_key='valid_urls';
    $page=$this->cache->redis->get($cache_key);
    
    if(!$page)$page=0;
    
    $dom=new DOMDocument('1.0','UTF-8');
    $dom->formatOutput = true;
    
    $col=$dom->getElementsByTagName('urlset');
    if( !empty( $col ) )$root=$col->item(0);
    else{
        $root=$dom->createElement('urlset');
        $dom->appendChild( $root );
        
        $root->setAttribute('xsi:schemaLocation','http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
        $root->setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
        $root->setAttribute('xmlns','http://www.sitemaps.org/schemas/sitemap/0.9');     
    }
    
    # does a `page` node exist - if so use the value as the $page variable
    $col=$com->getElementsByTagName('page');
    if( !empty( $col ) )$page=intval( $col->item(0)->nodeValue );
    
    
    $this->load->model('productnew/productnew_es6_m');
    $urls=$this->db->query("SELECT `url` FROM `product_data` where `active` = 1 limit ".$page.",1000")->result();
    
    foreach( $urls as $val ){
        $url = $dom->createElement('url');
        $root->appendChild($url);

        $lastmod = $dom->createElement('lastmod',date("Y-m-d"));
        $url->appendChild($lastmod);

        $page++;
    }
    
    
    $node=$dom->createElement( 'page',$page );
    $root->insertBefore( $node,$root->firstChild );
    
    
    if( empty( $urls ) )$page=0;
    $dom->save( $file );
    $this->cache->redis->save( $cache_key,$page,432000 );
}
,

附加到文档看起来不错,但是您没有打开要从磁盘附加到的文件。因此,在每个页面上,您从 XML 中的 0 个 url 开始并附加到空的根节点。

但是每次执行 cron 后,旧的 url 数据将被替换为最新的一次。

这正是您所描述的行为,听起来您一开始并没有加载 XML 文件,只需编写即可。

所以问题可能是如何打开一个 XML 文件,根据您的描述已经 append 看起来不错。

让我们回顾一下,通过颠倒你问题的介绍句:

我需要对 url 进行一些验证,并将有效的 url 附加到 xml 文件中。

所以我实现了一个 cron,它通过分页从 mysql 中一次获取 1000 行。

我有一个 mysql 查询,它获取了将近 5000 行的 url 数据(1 行包含 1 个 url)。

假设要附加每个 1000 url-set 的文件已经在磁盘上(第 2-5 页),您需要附加。但是,如果在第 1 页上的文件已经在磁盘上,您将附加到其他一些第 1-5 页。

所以看起来您只在第一页时编写了代码 - 创建一个新文档(并附加到它)。

尽管您有问题,附加确实有效,您自己编写:

旧的 url 数据正在被最新的一次替换。

唯一不起作用的是打开第 2 - 5 页上的文件。

那么让我们重新表述这个问题:如何打开一个 XML 文件?

但首先,变量 $page 并不代表上述第 1 - 5 页中的 page。它只是一个名称有问题的变量,$page 代表循环中到目前为止处理的 URL 数量,而不是分页中的页面。

不管它的名字是什么,我都会用它作为这个答案的价值。

所以现在让我们在 $page 不是 0 时打开现有文档进行追加:

...

$dom = new DOMDocument('1.0','UTF-8');
$dom->formatOutput = true;

if ($page !== 0) {
    $dom->load(dom_import_simplexml($xFile)->ownerDocument->documentURI)    ​
}


$col=$dom->getElementsByTagName('urlset');

...

只有在第一次运行时,您才会有所描述的文件是新创建的行为 - 在这种情况下它很好(在第一次运行 $page === 0 时)。

在任何其他情况下,$page 不是 0 并且文件是从磁盘打开的。

我已将您代码的其他部分放在一边,因此本示例仅介绍了这个 3 行 if 子句。

load($file) 函数的文档可在 PHP 文档中找到,以防万一到目前为止您错过了:

如果您想跟上进度,请尽量不要重复使用相同的变量名称。在这里,我不得不回收整个 SimpleXMLElement 并将其导入到 DOM 中,只是为了获取原始 xml-file-path 以打开文档 - 尽管它曾经在变量 $xFile 下,但它不再作为纯字符串可用。但这只是作为边距中的注释。

并且由于您已经在使用 Redis,您可能希望将 URL 排入队列并从那里进行处理,然后您可能不需要数据库分页。见Lists of the Redis Data-Types

然后,您还可以将好的 URL 放在第二个列表中。

通过两个列表,您甚至可以直接在 Redis 中不断查看进度。

最后完成后,您可以在一个事务中从 Redis 中的好 URL 中一次性写入整个文件。

如果您想在其上投入更多(最少)技术,请查看 Beanstalkd。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...