所以我的问题是,当我用一些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";
}
?>
答案 0 :(得分: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);
}
或者如果您使用的是某种类型的重命名是原子的,您可以写入临时文件并重命名旧文件而不是使用锁定。 (在这种情况下你不需要锁定,因为只要你用这个方法写,文件永远不会半读或半写。)
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());
}
答案 1 :(得分:1)
在使用xml时,您应该考虑使用像DOMDocument / XPath或simplexml这样的xml库。无论是否修复此错误,您都将达到XML处理您认为非常混乱的方式。
例如,查看SimpleXML和页面上的示例。