【问题标题】:How to get the text contents of an XML child element based on an attribute of its parent如何根据父元素的属性获取 XML 子元素的文本内容
【发布时间】:2016-10-07 09:11:22
【问题描述】:

这是我的 XML 数据

<categories>
    <category id="Id001" name="Abcd">
        <project> ID_1234</project>
        <project> ID_5678</project>
    </category>
    <category id="Id002" name="efgh">
        <project> ID_6756</project>
        <project> ID_4356</project>
    </category>
</categories>

我需要根据包含&lt;category&gt; 元素的name 属性获取每个&lt;project&gt; 元素的文本内容。

我将 Perl 与 XML::LibXML 模块一起使用。

例如,给定类别名称Abcd,我应该得到列表ID_1234ID_5678

这是我的代码

my $parser = XML::LibXML->new;

$doc = $parser->parse_file( "/cctest/categories.xml" );

my @nodes = $doc->findnodes( '/categories/category' );

foreach my $cat ( @nodes ) {
    my @catn = $cat->findvalue('@name');
} 

这给了我数组@catn 中的类别名称。但是如何获取每个项目的文本值呢?

【问题讨论】:

  • 你使用的是哪个解析器?
  • 嗨,我正在使用 XML::LibXML 来解析 xml 文件。
  • 您具体寻求什么输出?代码方面,你已经拥有了什么?
  • 请包含您已经编写的代码并说明您遇到的困难。您可以通过edit 链接edit 您的问题。有关如何使用该网站的更多信息,请参阅How to Ask
  • 我的 $parser = XML::LibXML->new; $doc = $parser->parse_file("/cctest/categories.xml");我的@nodes = $doc->findnodes('/categories/category'); foreach 我的 $cat(@nodes){

标签: perl xml-parsing


【解决方案1】:

到目前为止,您还没有展示您尝试过的内容,或者您​​想要的输出,所以我猜测了您要查找的内容。

使用XML::Twig,您可以执行以下操作:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> parse ( \*DATA );

foreach my $project ( $twig -> findnodes ( '//project' ) ) { 
    print join ",",  (map { $project -> parent -> att($_) } qw ( id name )), $project -> text,"\n"; 
}

__DATA__
<categories>
<category id="Id001" name="Abcd">
   <project> ID_1234</project>
   <project> ID_5678</project>
</category>
<category id="Id002" name="efgh">
   <project> ID_6756</project>
   <project> ID_4356</project>
</category>
</categories>

产生:

Id001,Abcd, ID_1234,
Id001,Abcd, ID_5678,
Id002,efgh, ID_6756,
Id002,efgh, ID_4356,

它通过使用findnodes 来定位任何元素“项目”来做到这一点。

然后从父级(类别)中提取“id”和“name”属性,并将其与该特定元素中的文本一起打印。

xpath是从XML中选择数据的强大工具,对于更集中的问题,我们可以给出更具体的答案。

因此,如果您正在寻找“Abcd”类别“下方”的所有项目,您可以:

foreach my $project ( $twig -> findnodes ( './category[@name="Abcd"]/project' ) ) { 
    print $project -> text,"\n";
}

【讨论】:

  • 嗨,我尝试使用 XML::Twig 并且成功了。感谢您的所有帮助:)
【解决方案2】:

这使用 XML::LibXML,这是您已经在使用的库。

您的 $cat 变量包含一个 XML 元素对象,您可以使用与顶级 $doc 对象相同的 findnodes()findvalue() 方法来处理它。

#!/usr/bin/perl

use strict;
use warnings;
# We use modern Perl here (specifically say())
use 5.010;

use XML::LibXML;

my $doc = XML::LibXML->new->parse_file('categories.xml');

foreach my $cat ($doc->findnodes('//category')) {
  say $cat->findvalue('@name');
  foreach my $proj ($cat->findnodes('project')) {
    say $proj->findvalue('.');
  }
}

【讨论】:

  • @Dave Cross:非常感谢。甚至这个提供的代码也帮助我满足了我的要求。
【解决方案3】:

你可以试试XML::Simple

use strict;
use warnings;
use XML::Simple;
use Data::Dumper

my $XML_file  = 'your XML file';
my $XML_data;
#Get data from your XML file
open(my $IN, '<:encoding(UTF-8)', $XML_file) or die "cannot open file $XML_file";
{
   local $/;
   $XML_data = <$IN>;
}
close($IN);
#Store XML data as hash reference
my $xmlSimple = XML::Simple->new(KeepRoot   => 1);
my $hash_ref = $xmlSimple->XMLin($XML_data);
print Dumper $hash_ref;

哈希参考如下:

$VAR1 = {
          'categories' => {
                          'category' => {
                                        'efgh' => {
                                                  'id' => 'Id002',
                                                  'project' => [
                                                               ' ID_6756',
                                                               ' ID_4356'
                                                             ]
                                                },
                                        'Abcd' => {
                                                  'id' => 'Id001',
                                                  'project' => [
                                                               ' ID_1234',
                                                               ' ID_5678'
                                                             ]
                                                }
                                      }
                        }
        };

现在获取您想要的数据:

foreach(@{$hash_ref->{'categories'}->{'category'}->{'Abcd'}->{'project'}}){
  print "$_\n";
}

结果是:

ID_1234
ID_5678

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多