【问题标题】:Extract attributes and values from XML file in perl在 perl 中从 XML 文件中提取属性和值
【发布时间】:2013-04-08 21:10:47
【问题描述】:

这是我从 Stanford CoreNLP 获得的输出 XML 文件的一部分:

<collapsed-ccprocessed-dependencies>  
      <dep type="nn">
        <governor idx="25">Mullen</governor>
        <dependent idx="24">Ms.</dependent>
      </dep>
      <dep type="nsubj">
        <governor idx="26">said</governor>
        <dependent idx="25">Mullen</dependent>
      </dep>
    </collapsed-ccprocessed-dependencies>
  </sentence>
</sentences>
<coreference>
  <coreference>
    <mention representative="true">
      <sentence>1</sentence>
      <start>1</start>
      <end>2</end>
      <head>1</head>
    </mention>
    <mention>
      <sentence>1</sentence>
      <start>33</start>
      <end>34</end>
      <head>33</head>
    </mention>
  </coreference>
 </coreference>
<mention representative="true">
      <sentence>1</sentence>
      <start>6</start>
      <end>9</end>
      <head>8</head>
    </mention>
    <mention>
      <sentence>1</sentence>
      <start>10</start>
      <end>11</end>
      <head>10</head>
    </mention>
  </coreference>
  <coreference>   

如何使用 Perl 对其进行解析,以便得到如下内容:

1. sentence 1, head 1
   sentence 1, head 33
2. sentence 1, head 8
   sentence 1, head 10

我尝试过使用 XML::Simple,但输出不容易理解。这是我所做的: 使用 XML::Simple; 使用 Data::Dumper;

$outfile = $filename.".xml";
$xml = new XML::Simple;

$data = $xml -> XMLin($outfile);
print Dumper($data);

【问题讨论】:

  • 你必须展示你迄今为止所尝试的。

标签: perl xml-parsing stanford-nlp


【解决方案1】:

XML::Simple 具有最难使用的界面。你可以使用类似的东西

use XML::LibXML qw( );

my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($xml);

my $coref_count;
for my $coref_node ($doc->findnodes('//coreference/coreference')) {
   ++$coref_count;

   my $mention_count;
   for my $mention_node ($coref_node->findnodes('mention')) {
      ++$mention_count;

      my $sentence = $mention_node->findvalue('sentence/text()');
      my $head     = $mention_node->findvalue('head/text()');

      my $prefix = "$coref_count.";
      $prefix = ' ' x length($prefix) if $mention_count == 1;

      print "$prefix sentence $sentence, head $head\n";
   }
}

【讨论】:

  • 谢谢。我不断收到语法错误,提示缺少“
  • 有文件可以使用-&gt;parse_file($qfn)
  • 哦,我把它用作 -> parsefile 可能因此而无法工作。再次感谢!
【解决方案2】:

遗憾的是,XML::Simple 是第一个声称拥有 Simple 命名空间的人。它的实现可能很简单,但使用起来并不简单,除非在最微不足道的情况下。如果您想要类似的东西,那么XML::Smart 提供了一个嵌套数据结构 API,但它做得更好。

值得庆幸的是,优秀的 Perl XML 模块有很多选择。 XML::Twig 就是其中之一,它允许您指定在解析期间遇到 XML 数据中的特定元素时将执行的回调子例程。

此程序使用XML::Twig,并在coreference[mention] 上设置回调,即至少有一个mention 子元素的coreference 元素。

处理程序子例程中的代码不进行任何检查,并假定始终存在至少两个mention 子元素,每个子元素都有一个sentence 和一个header 元素。这些节点的文本值以您描述的格式输出。

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(twig_handlers => {
  'coreference[mention]' => \&handle_coreference
});
$twig->parsefile('myxml.xml');

my $n;
sub handle_coreference {

  my ($twig, $elt) = @_;

  my @mentions = $elt->children('mention');

  for my $i (0 .. $#mentions) {
    printf "%s sentence %d, head %d\n",
      $i == 0 ? sprintf '%3d.', ++$n : '    ',
      map $mentions[$i]->first_child_trimmed_text($_), qw/ sentence head /;
  }
}

输出

  1. sentence 1, head 1
     sentence 1, head 33
  2. sentence 1, head 8
     sentence 1, head 10

【讨论】:

  • 非常感谢!有用。我被这个问题困扰了很多天。非常感谢您的帮助。
  • 我怀疑总会有两次提及。
  • @ikegami:不幸的是,我们对这些数据一无所知。尽管如此,我已经概括了解决方案,因为它也更整洁。
【解决方案3】:

类似:

use strict;
use warnings;

use XML::Rules;

my $mention_cnt;
my $ref_cnt = 1;
my @rules = (
  coreference => sub {
    $ref_cnt++ if $mention_cnt;
    $mention_cnt = 0;
  },
  mention => sub {
    my $d = $_[1];
    my $str = $mention_cnt++ ? " " x 6 : sprintf("%-6s", "$ref_cnt.");
    print "$str sentence: $d->{sentence} head: $d->{head}\n";
  },
  'sentence,head' => 'content',
);

my $xr = XML::Rules->new(
  rules => \@rules,
);
$xr->parse($xml);

【讨论】:

  • 现在已经应用了正确的格式,请注意所需的输出。
  • @ikegami - 哦,好吧,他确实说过'类似......' :-) 也许我会更新,也许我不会......或者任何有编辑能力的人都可以更新这个答案...
  • 我是 perl 新手,除了很多其他事情之外,我仍在尝试理解解析文件所涉及的步骤。如果您能更新它,将不胜感激。
  • 非常感谢。一个快速的问题,在哪里提供输入?它是 $xml 变量吗?我一直在该行收到语法错误。
  • 是的,假设 $xml 是一个 XML 字符串,因为 XML 不能自发地创建自己。或者它可能来自文件句柄,或者使用 parse_file() 代替,来自文件。
猜你喜欢
  • 1970-01-01
  • 2011-02-12
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 2020-08-18
  • 1970-01-01
  • 2014-02-21
相关资源
最近更新 更多