【问题标题】:simple XML question for perl - how to retrieve specific elementsperl 的简单 XML 问题 - 如何检索特定元素
【发布时间】:2011-02-15 12:04:43
【问题描述】:

我正在尝试弄清楚如何循环遍历 XML,但我已经阅读了很多内容,但我仍然陷入困境。这是信息:

我正在使用 wordnik api 通过 XML::Simple 检索 XML:

 $content = get($url);
 $r = $xml->XMLin("$content");

实际的 XML 如下所示:

<definitions>
−
<definition sequence="0" id="0">
−
<text>
To withdraw one's support or help from, especially in spite of duty, allegiance, or responsibility; desert:  abandon a friend in trouble. 
</text>
<headword>abandon</headword>
<partOfSpeech>verb-transitive</partOfSpeech>
</definition>
−
<definition sequence="1" id="0">
−
<text>
To give up by leaving or ceasing to operate or inhabit, especially as a result of danger or other impending threat:  abandoned the ship. 
</text>
<headword>abandon</headword>
<partOfSpeech>verb-transitive</partOfSpeech>
</definition>
−
<definition sequence="2" id="0">
−
<text>
To surrender one's claim to, right to, or interest in; give up entirely. See Synonyms at relinquish.
</text>
<headword>abandon</headword>
<partOfSpeech>verb-transitive</partOfSpeech>
</definition>
−
<definition sequence="3" id="0">

...

我想要的只是 FIRST 定义的词性。我正在使用此代码,但它正在获取 LAST 定义的 POS:

    if($r->{definition}->{0}->{partOfSpeech}) {
      $pos = $r->{definition}->{0}->{partOfSpeech};
     }
else { $pos = $r->{definition}->{partOfSpeech}; }

我对此感到非常尴尬,因为我知道有一种明显更好的方法可以做到这一点。我很想得到像这个工作一样简单的东西,这样我就可以更普遍地遍历元素。但是它对我不起作用(不知道要参考什么)。我尝试了以下多种变体 - 这只是我的最后一次尝试:

 while (my ($k, $v) = each %{$r->{definitions}->{definition}[0]->{sequence}->{partOfSpeech}}) {
  $v =~ s/'/'"'"'/g;
  $v = "'$v'";
  print "export $k=$v\n";
 }

最后,当我执行“打印 Dumper($r)”时,它给了我这个:

$VAR1 = {
          'definition' => {
                          '0' => {
                                 'partOfSpeech' => 'noun',
                                 'sequence' => '6',
                                 'text' => 'A complete surrender of inhibitions.',
                                 'headword' => 'abandon'
                               }
                        }
        };

(你看到的那个“名词”是最后一个(第 6 个)定义/partofspeech 元素)。


根据下面 RC 的回答,我的新代码如下所示:

$content = get($url);
$r = $xml->XMLin("$content", KeyAttr => { definition => 'sequence'});
while (my ($k, $v) = each %{$r->{definition}}) {
    $v=$r->{definition}->{$k}->{partOfSpeech};
    print "export $k=$v\n";
}

这会打印出以下内容:

export 6='noun'
export 4='verb-transitive'
export 1='verb-transitive'
export 3='verb-transitive'
export 0='verb-transitive'
export 2='verb-transitive'
export 5='noun'

所以这很好,它正在导出正确的对。但现在的问题是订单已关闭(这似乎很可能是 Wordnik 的问题,而不是编程问题)。如何按键排序?像这样?

sort($r->{definition});

【问题讨论】:

    标签: xml perl


    【解决方案1】:

    来自XML::Simple文档:

    注 1:默认值为 'KeyAttr' 是 ['name', 'key', 'id']。如果 您不想折叠输入或 在输出上展开你必须设置 此选项为空列表 禁用该功能。

    我认为将KeyAttr =&gt; { definition =&gt; 'sequence' } 添加到XMLin 选项可能会解决您的问题。

    【讨论】:

    • thx RC - 这真的很有帮助,并且朝着正确的方向发展。但我现在有一个新的(较小的)问题。有关附加信息,请参阅我编辑的帖子。
    • foreach my $k (sort keys %{$r-&gt;{definition}}) { 替换while (my ($k, $v) = each %{$r-&gt;{definition}}) { 应该可以解决问题
    【解决方案2】:

    也可以使用XML::Twig为你遍历文件,帮助提取数据:

    use XML::Twig;
    
    my $content = do { local $/; <DATA> };      # get data
    
    XML::Twig->new(twig_handlers => {
        definition => sub {
            warn "---\n",
                "sequence = ",     $_->att('sequence'), "\n",
                "text = ",         $_->first_child_trimmed_text('text'), "\n",
                "headword = ",     $_->first_child_trimmed_text('headword'), "\n",
                "partOfSpeech = ", $_->first_child_trimmed_text('partOfSpeech'), "\n";
            $_->purge;
        },
    })->parsestring($content);
    

    这也更有效,因为不必将整个结构加载到内存中(purge 方法正在为您清理处理过的数据)。

    【讨论】:

      【解决方案3】:

      你可以试试WWW::Wordnik::API(我是作者)

      【讨论】:

        猜你喜欢
        • 2015-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-15
        • 2012-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多