【问题标题】:Parsing XML and TXT files in PHP在 PHP 中解析 XML 和 TXT 文件
【发布时间】:2016-05-21 14:56:33
【问题描述】:

我有一个 Text.xml 文件,其中包含一些文本和该文本中的参考书目。它看起来像这样:

Text.xml

<p>…blabla S.King (1987). Bla bla bla J.Doe (2001) blabla bla J.Martin (1995) blabla…</p>

我有一个 Reference.txt 文件,其中包含书目参考列表和每个参考的 ID 号。它看起来像这样:

Reference.txt

b1#S.King (1987)
b2#J.Doe (2001)
b3#J.Martin (1995)

我想从 Reference.txt 中找到所有参考书目到 Text.xml,然后添加一个带有 ID 的标签。目标是 TextWithReference.xml 必须如下所示:

TextWithReference.xml

<p>…blabla <ref type="biblio" target=“b1”>S.King (1987)</ref>. Bla bla bla <ref type="biblio" target=“b2”>J.Doe (2001)</ref> blabla bla <ref type="biblio" target=“b3”>J.Martin (1995)</ref> blabla…</p>

为此,我使用了一个 php 文件。

搜索和替换.php

<?php
$handle = fopen("Reference.txt","r");
while(!feof($handle))
{
    $ligne = fgets($handle,1024);
    $tabRef[] = $ligne;
}   
fclose($handle);

$handleXML = fopen("Text.xml","r");
$fp = fopen("TextWithReference.xml", "w");
while(!feof($handleXML))
{
    $ligneXML = fgets($handleXML,2048);
        for($i=0;$i<sizeof($tabRef);$i++)
        {
            $tabSearch = explode('/#/',$tabRef[$i]);
            $xmlID = $tabSearch[0];
            $searchString = trim($tabSearch[1]);
            if(preg_match('/$searchString/',$ligneXML))
            {
                $ligneXML = preg_replace('/($searchString)/','/<ref type=\"biblio\" target=\"#$xmlID\">\\0</ref>/',$ligneXML);
            }

        }
    fwrite($fp, $ligneXML);
}
fclose($handleXML);
fclose($fp);

?>

问题是这个 php 脚本只是复制 TextWithReference.xml 中的 Text.xml 没有识别参考书目,也没有添加标签……

非常感谢您的帮助!

【问题讨论】:

  • 如果您的 Text.xml 确实是格式良好的 xml,我认为更快的方法(干净,使用很少的内存)是使用组合 XMLReader/XMLWriter 来创建 TextWithReference.xml。跨度>
  • 你能为你的两个xml文件提供一个url吗?
  • 在创建 $tabRef 时,您应该修剪和分解搜索字符串,而不是针对 XML 文件中的每一行。
  • 是的,Text.xml 是格式良好的 xml。您的意思是直接在 XmlEditor 中使用正则表达式还是使用 xslt?
  • 不,XMLReader 是一个内置的 PHP 类,旨在逐个元素(开始标记、注释、文本节点...)解析 XML 文件元素,而 XMLWriter 通过以下方式写入 XML 文件元素元素也是。 XSLT 为什么不呢,但它不是很方便,而且 PHP 速度特别慢。

标签: php xml search replace preg-replace


【解决方案1】:

您的代码存在许多问题。

  1. 搜索字符串包含正则表达式中的特殊字符,例如括号。如果您想从字面上匹配它们,则需要转义它们。 preg_quote 函数执行此操作。

  2. 您的文件读取循环不正确。 while (!feof()) 不是读取文件的正确方法,因为直到您在文件末尾读取 之后 才会设置 EOF 标志。因此,您将花费额外的时间来完成这些循环。正确的写法是while ($ligne = fgets())

  3. 在尝试替换 $searchString$xmlID 的字符串周围有单引号。变量仅在双引号内替换。见What is the difference between single-quoted and double-quoted strings in PHP?

  4. 您不需要在preg_replace 中的替换字符串周围放置/ 分隔符。

  5. 每次处理Text.xml 中的行时,从Reference.txt 中分解、修剪和转义行是低效的。在阅读 Reference.txt 时执行一次。

  6. 在替换字符串中,使用$0 替换源中匹配的文本。 \0 是一种过时的方法,不建议使用。

  7. 您不需要在正则表达式中的搜索字符串周围加上括号,因为您没有在替换中使用$1 捕获组。由于它围绕整个正则表达式,它与$0 相同。

这是工作重写:

<?php
$handle = fopen("Reference.txt","r");
$tabRef = array();
while($ligne = trim(fgets($handle,1024))) {
    list($xmlID, $searchString) = explode('#', $ligne);
    $tabRef[] = array($xmlID, preg_quote($searchString));
}   
fclose($handle);

$handleXML = fopen("Text.xml","r");
$fp = fopen("TextWithReference.xml", "w");
while($ligneXML = fgets($handleXML,2048)) {
    foreach ($tabRef as $tabSearch) {
        $xmlID = $tabSearch[0];
        $searchString = $tabSearch[1];
        if(preg_match("/$searchString/",$ligneXML)) {
            $ligneXML = preg_replace("/$searchString/","<ref type=\"biblio\" target=\"#$xmlID\">$0</ref>",$ligneXML);
        }
    }
    fwrite($fp, $ligneXML);
}
fclose($handleXML);
fclose($fp);

?>

另一项改进利用了将使用数组作为preg_replace 的搜索和替换参数的能力,而不是使用循环。在读取Reference.txt 时,在那里创建正则表达式和替换字符串,并将它们分别放入一个数组中。

<?php
$handle = fopen("Reference.txt","r");
$search = array();
$replacement = array();
while($ligne = trim(fgets($handle,1024))) {
    list($xmlID, $searchString) = explode('#', $ligne);
    $search[] = "/" . preg_quote($searchString) . "/";
    $replacement[] = "<ref type=\"biblio\" target=\"#$xmlID\">$0</ref>";
}   
fclose($handle);

$handleXML = fopen("Text.xml","r");
$fp = fopen("TextWithReference.xml", "w");
while($ligneXML = fgets($handleXML,2048)) {
    $ligneXML = preg_replace($search,$replacement,$ligneXML);
    fwrite($fp, $ligneXML);
}
fclose($handleXML);
fclose($fp);

?>

【讨论】:

  • 非常感谢!它就像一个魅力!而且你的脚本要快得多!我非常感谢您的详细解释;这对我很有用!非常感谢!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 2012-12-22
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
相关资源
最近更新 更多