如何使用perl基于另一个节点值从xml获取节点值

时间:2016-12-02 08:18:29

标签: xml perl

我的projects.xml文件如下:

<projects>
    <project>
        <id>ID_ABCD1</id>
        <name>ptest1</name>
    </project>
    <project>
        <id>IDB_abcd</id>
        <name>ptest1</name>
        <branch>bnm1</branch>
        <branched_from_id>ID_ABCD1</branched_from_id>
        <branched_from_version>111</branched_from_version>
    </project>
    <project>
        <id>ID_ABCD2</id>
        <name>ptest2</name>
    </project>
    <project>
        <id>IDB_abcd2</id>
        <name>ptest2</name>
        <branch>bnm2</branch>
        <branched_from_id>ID_ABCD2</branched_from_id>
        <branched_from_version>111</branched_from_version>
    </project>
</projects>

在我现有的代码中,我根据从另一个文件categories.xml获得的项目ID获取项目名称。

对于每个项目名称,我必须搜索它有任何branch元素,如果元素存在,那么我必须得到 相应的branch名称和branched_from_version

branched_from_id值是某个其他项目的ID。

#!/usr/bin/env perl

use strict;

use XML::LibXML;
use File::Basename;
use File::Find::Rule;
use XML::Twig;

my $cat_xml  = '/home/Ras/categories.xml';
my $twig     = XML::Twig->parse( $cat_xml );
my $doc      = XML::LibXML->new->parse_file( $cat_xml );

my $proj_xml = '/home/Ras/projects.xml';
my $twigp    = XML::LibXML->new->parse_file( $proj_xml );

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

my $catname  = "/home/Ras/category.txt";

open FH, "> $catname" or warn "not able to open catname file";

foreach my $catnode ( @nodes ) {
    my @catn = $catnode->findvalue( '@name' );
    print FH "@catn \n";
}

my @catlist = `cat /home/Ras/category.txt`;

foreach my $cat ( @catlist ) {

    chomp( $cat );
    $cat =~ s/^\s+|\s$//g;

    my $path = "./category[\@name=\"$cat\"]/project";

    foreach my $project ( $twig->findnodes( "$path" ) ) {

        my $projout = $project->text;

        foreach my $projname ( $twigp->findvalue( "/projects/project[id = '$projout']/name" ) ) {

        }
    }
}

在上面的代码$projout中包含我的project.xml文件的ID值。但那些branch节点的ID值不存在。

我在$projname中有名字值。因此,根据$projname中的名称值,我需要获得相应的branch值和branched_from_version值。

1 个答案:

答案 0 :(得分:1)

它有点简化,但我认为你正在尝试这样做:

#!/usr/bin/env perl
use warnings;
use strict;

use XML::Twig;

my $twig = XML::Twig -> parsefile ( 'test.xml' );
my $project = 'ptest2'; 

if ( $twig -> get_xpath("//project/name[string()=\"$project\"]" ) ) {
    print $twig -> get_xpath("//project/name[string()=\"$project\"]",0 ) -> text, " exists\n";
    foreach my $branch ( $twig -> get_xpath("//project/name[string()=\"$project\"]/../branched_from_id/..",0 ) ) {
       print "$project : ", $branch -> first_child_text('branched_from_id'), " => ", $branch -> first_child_text('branched_from_version'),"\n";
    }
}

我不得不削减它,因为我没有你的项目清单。但是,这将使用XML::Twig s get_xpath来查找项目名称 - 尽管请注意,它并不区分是否为支票的第一部分分支。

然后根据“匹配”的所有分支机构推出xpath匹配。