0

所以我的问题是,当我用一些 PHP 行编辑 XML 文件(如下)时,第一次一切正常,然后它会删除错误行并在错误的位置创建新行。

这里是用于删除行的 PHP 脚本:

<?php
session_start(); 

// The file
$filePath = '/....../test/test.xml';

// Grab file into an array, by lines
$fileArr = file($filePath);

// Remove desired line
unset($fileArr[7]); // $fileArr[15] == line #16
unset($fileArr[16]); // idem
unset($fileArr[25]); // idem

//Put back with PHP5
file_put_contents($filePath, implode('', $fileArr ));

session_destroy(); 
?>

这里是写新行的 PHP 脚本

<?php
session_start(); 

// The file
$filePath = '/....../test/test.xml';

// Grab file into an array, by lines
$fileArr = file($filePath);

//Change
$etichettaasse = "\t\t\t\t<string>\t14 gen</string>\n\r";
$medianord =  "\t\t\t\t<number>\t280\t</number>\n\r";
$mediasud =  "\t\t\t\t<number>\t280\t</number>\n\r";

// Replace line
$fileArr[11] = $etichettaasse;
$fileArr[19] = $medianord;
$fileArr[27] = $mediasud;

// Implode and save
file_put_contents($filePath, implode('', $fileArr ));

session_destroy(); 
?>

这里是原始XML:

<chart>
<axis_category color='ffffff' skip='0' size='12' alpha='80' />
<axis_value color='ffffff' skip='10' size='12' show_min='false' min="80" max="130"  />
<chart_border top_thickness='1' bottom_thickness='1' left_thickness='1' right_thickness='1' />              
<chart_data>
    <row>
        <null/>
            <string>    3 dic</string>
            <string>    10 dic</string>
            <string>    17 dic</string>
            <string>    24 dic</string>
            <string>    31 dic</string>

    </row>
    <row>
        <string>Media Nord</string>
            <number>    102.72  </number>
            <number>    101.60  </number>
            <number>    101.85  </number>
            <number>    101.84  </number>
            <number>    101.84  </number>

    </row>
    <row>
        <string>Media Sud</string>
            <number>    102.28  </number>
            <number>    101.24  </number>
            <number>    101.70  </number>
            <number>    101.88  </number>
            <number>    101.88  </number>

    </row>
</chart_data>
</chart>

第一轮PHP脚本后,按要求更新:

<chart>
<axis_category color='ffffff' skip='0' size='12' alpha='80' />
<axis_value color='ffffff' skip='10' size='12' show_min='false' min="80" max="130"  />
<chart_border top_thickness='1' bottom_thickness='1' left_thickness='1' right_thickness='1' />              
<chart_data>
    <row>
        <null/>
            <string>    10 dic</string>
            <string>    17 dic</string>
            <string>    24 dic</string>
            <string>    31 dic</string>
            <string>    14 gen</string>

    </row>
    <row>
        <string>Media Nord</string>
            <number>    101.60  </number>
            <number>    101.85  </number>
            <number>    101.84  </number>
            <number>    101.84  </number>
            <number>    280 </number>

    </row>
    <row>
        <string>Media Sud</string>
            <number>    101.24  </number>
            <number>    101.70  </number>
            <number>    101.88  </number>
            <number>    101.88  </number>
            <number>    280 </number>

    </row>
</chart_data>

PHP脚本第二轮之后:

<chart>
<axis_category color='ffffff' skip='0' size='12' alpha='80' />
<axis_value color='ffffff' skip='10' size='12' show_min='false' min="80" max="130"  />
<chart_border top_thickness='1' bottom_thickness='1' left_thickness='1' right_thickness='1' />              
<chart_data>
    <row>
        <null/>
            <string>    17 dic</string>
            <string>    24 dic</string>
            <string>    14 gen</string>
            <string>    14 gen</string>

    </row>
    <row>
        <string>Media Nord</string>
            <number>    101.60  </number>
            <number>    101.84  </number>
            <number>    280 </number>


            <number>    280 </number>

    <row>
        <string>Media Sud</string>
            <number>    101.24  </number>
            <number>    101.70  </number>
            <number>    280 </number>


    </row>
            <number>    280 </number>

如果我只能拥有一个 PHP 文件而不是 2 个,我也会很高兴,但我不知道该怎么做。

这是修改此 XML 文件的最佳方法,还是有其他方法?

请注意,用户将写入 HTML 的新行。

我有这个“开始”脚本用于删除我要删除的内容。

你怎么看呢?

<?php
$file = '/...../test.xml';


$fp = fopen(file,"w"); // open it for WRITING ("w")

if (flock($fp, LOCK_EX)) {

    //do actions here
    $xml = file_get_contents($file);
    $sxe = simplexml_load_string($xml);

    echo '<pre>';

    // "delete the 1th string of row 1, etc."
    unset($sxe->chart_data->row[0]->string[0]);
    unset($sxe->chart_data->row[1]->number[0]);
    unset($sxe->chart_data->row[2]->number[0]);

    $sxe->chart_data->row[0]->addChild('string', 'test');
    $sxe->chart_data->row[1]->addChild('number', '999');
    $sxe->chart_data->row[2]->addChild('number', '9999');

    file_put_contents($file, $sxe->asXML());


    // unlock the file
    flock($fp, LOCK_UN);

} else {

    // flock() returned false, no lock obtained
    print "Could not lock $file!\n";
}

?>
4

2 回答 2

2

问题是当您unset()是数组成员时,您会更改行号。这很容易证明:

$origfile = array(
    "line1\n",
    "line2\n",
    "line3\n",
);

unset($file[1]); // delete line 2

$round1file = implode('', $file); // "write the file"

结果是两行文件,而不是三行文件!

line1
line3

因此,当您再次读取它时,您的数组将如下所示:

$round1file = array("line1\n","line3\n");

如果你再次删除第 2 行,你显然会留下array("line1\n")

直接的解决方案是用空行替换该行,而不是取消设置数组成员,即$fileArr[7] = "\n"代替unset($fileArr[7]).

但是,您正在做的事情完全是疯狂的。这是一个 XML 文件,因此您需要使用 XML 库对其进行解析和编写,否则我保证您迟早会得到无效的 XML !此外,您不能安全地覆盖多个进程可能正在使用的文件——您需要使用某种文件锁定或适当的数据库。

对于文件锁定,您可以使用如下一对函数:

function file_get_contents_locked($filename)
{
    $fp = fopen($filename, 'rb');
    if ($fp===FALSE) {
        throw new RuntimeException("Could not open file '{$filename}'");
    }
    if (flock($fp, LOCK_SH)) {
        $data = stream_get_contents($fp);
        flock($fp, LOCK_UN);
        fclose($fp);
        return $data;
    } else {
            fclose($fp);
        throw new RuntimeException("Could not acquire lock on file '{$filename}'");
    }
}


function file_put_contents_locked($filename, $data)
{
    return file_put_contents($filename, $data, LOCK_EX);
}

或者,如果您在某种重命名是原子的 *nix 上,您可以写入临时文件并重命名旧文件,而不是使用锁定。(在这种情况下您不需要锁定,因为只要您使用此方法写入,文件就永远不会半读或半写。)

function write_atomic($fullfilename, $data) {
    $tmpname = tempnam(dirname($fullfilename), 'write_atomic-');
    if (FALSE!==file_put_contents($tmpname, $data)) {
        rename($tmpname, $fillfilename);
    }
    unlink($tmpname);
}

对于 XML 操作,两个简单的选项是简单但功能较弱的SimpleXML和更复杂但功能更强大的DOMDocument 。(您也可以使用 XMLReader 和 XMLWriter,但它们更难使用且速度更慢——仅当您无法一次将整个 XML 文件放入内存时才需要它们。)

这是一个帮助您入门的示例。查看链接的文档以获取更多详细信息:

function delete_xml_stuff($filename)
{
    $xml = file_get_contents_locked($filename);
    $sxe = simplexml_load_string($xml);
    // e.g., "delete the 2th string of row 1"
    unset($sxe->chart_data->row[0]->string[1]);
    file_put_contents_locked($filename, $sxe->asXML());

    // if you have more complex criteria, use DOMDocument:

    $d = new DOMDocument();
    $d->loadXML($xml);
    $xp = new DOMXPath($d);
    $results = $xp->query('//chart_data/row[2]/*[3]');
    if ($results->length) {
        $row2column3 = $results->item(0);
        $row2column3->parentNode->removeChild($row2column3);
    }
    file_put_contents_locked($d->saveXML());
}
于 2013-01-13T03:59:27.177 回答
1

在使用 xml 时,您应该考虑使用 DOMDocument/XPath 或 simplexml 之类的 xml 库。无论是否修复此错误,您都会达到一个地步,即按照您认为的方式处理 XML 会变得非常混乱。

例如查看SimpleXML和页面上的示例。

于 2013-01-13T03:32:16.773 回答