【问题标题】:Parsing XML file with perl - regex使用 perl 解析 XML 文件 - 正则表达式
【发布时间】:2010-06-03 09:25:44
【问题描述】:

我只是 perl 的初学者,非常迫切需要准备一个小脚本,从 xml 文件中获取前 3 项内容并将它们放入一个新文件中。 下面是一个 xml 文件的示例:

    <article>
  {lot of other stuff here}
</article>
<article>
  {lot of other stuff here}
</article>
<article>
  {lot of other stuff here}
</article>
<article>
  {lot of other stuff here}
</article>

我想做的是获取前 3 个项目以及它们之间的所有标签并将其放入另一个文件中。 感谢您提前提供的所有帮助 问候 彼得

【问题讨论】:

标签: regex perl


【解决方案1】:

Never ever use Regex to handle markup languages.

这个答案的原始版本(见下文)使用XML::XPath。格兰特麦克莱恩在 cmets 中说:

XML::XPath 是一个古老且无人维护的模块。 XML::LibXML 是一个现代化的维护模块,具有几乎相同的 API,而且速度也更快。

所以我制作了一个使用XML::LibXML 的新版本(感谢格兰特):

use warnings;
use strict;
use XML::LibXML;

my $doc   = XML::LibXML->load_xml(location => 'articles.xml');
my $xp    = XML::LibXML::XPathContext->new($doc->documentElement);
my $xpath = '/articles/article[position() < 4]';

foreach my $article ( $xp->findnodes($xpath) ) {
  # now do something with $article
  print $article.": ".$article->getName."\n";
}

对我来说,这是打印出来的:

XML::LibXML::Element=SCALAR(0x346ef90):文章 XML::LibXML::Element=SCALAR(0x346ef30):文章 XML::LibXML::Element=SCALAR(0x346efa8):文章

相关文档的链接:


答案的原始版本,基于XML::XPath 包:

use warnings;
use strict;
use XML::XPath;

my $xp    = XML::XPath->new(filename => 'articles.xml');
my $xpath = '/articles/article[position() < 4]';

foreach my $article ( $xp->findnodes($xpath)->get_nodelist ) {
  # now do something with $article
  print $article.": ".$article->getName ."\n";
}

为我打印这个:

XML::XPath::Node::Element=REF(0x38067b8):文章 XML::XPath::Node::Element=REF(0x38097e8):文章 XML::XPath::Node::Element=REF(0x3809ae8):文章

查看文档以了解您可以使用它们做什么。

【讨论】:

  • 这是一个正则表达式可以轻松完成工作的情况。
  • @Snake Plissken:不,不是。正则表达式从不适合这种工作,无论它看起来多么“简单”。 XPath+编程语言 X(在这种情况下是 Perl)是,或者 XSLT 是。正则表达式不是。
  • 你太傻了。在这种情况下,正则表达式可以轻松完成这项工作。如果有人要求您复制非 XML 文件,直到某些内容被看到 3 次,您会怎么做?
  • @Snake Plissken:我不是傻。我只是想避免在何时使用适当的解析器方面变得聪明。 Perl 中内置了一个很好的 XML 解析器,绝对没有理由不使用它。 (这不是“哦该死,我必须使用解析器,因为这对于正则表达式来说太复杂了”,而是“哦该死,我不能使用解析器,因为我使用的语言不提供解析器”。后者几乎从来没有。)
  • 仅供参考,XML::XPath 是一个古老且无人维护的模块。 XML::LibXML 是一个现代的、维护的模块,具有几乎相同的 API,而且速度也更快。
【解决方案2】:

这里:

 open my $input, "<", "file.xml" or die $!;
 open my $output, ">", "truncated-file.xml" or die $!;
 my $n_articles = 0;
 while (<$input>) {
      print $output $_;
      if (m:</article>:) {
           $n_articles++;
           if ($n_articles >= 3) {
                last;
           }
      }
 }         
 close $input or die $!;
 close $output or die $!;

你真的不需要 XML 解析器来完成这么简单的工作。

【讨论】:

  • 该脚本所做的是将 file.xml 的所有内容复制到 truncated-file.xml
  • 那么你的调试时间到了。无论如何,如果这不起作用,您可以使用另一个答案。
  • 我指的是这个线程上的另一个答案:stackoverflow.com/questions/2964637/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
相关资源
最近更新 更多