2014-03-26 58 views
2
use strict; 
use warnings; 
use Data::Dumper; 
use XML::Twig; 
use Getopt::Long; 
use Pod::Usage; 
my %VERSION_HASH; 
my $BRANCH_NAME; 
my $HELP; 
my $DEFAULT_XML; 
my $VERSIONED_XML; 
GetOptions(
    "help"   => \$HELP, 
    "branch=s"  => \$BRANCH_NAME, 
    "defaultxml=s" => \$DEFAULT_XML, 
    "versionedxml=s" => \&VERSIONED_XML, 
) or pod2usage({ -verbose => 1 }); 
if (defined $HELP) { 
    pod2usage({ -verbose => 2 }); 
} 
my $UPDATE_XML= XML::Twig->new( 
    twig_handlers => { 
     q{project[@path =~ /\bopensource\b/]} => \&fix_opensource_revision, 
     q{default} => \&update_default_branch_name, 
     q{project[@path !~ /\bopensource\b/]} => \&remove_revision_attribute, 
     q{project[@path =~ /\bdocs\b/]} => \&fix_docs_to_master, 
     q{remote[@name =~ /\bgit-rc\b/]} => sub { $_->delete; }, 
    }, 
); 
my $REF_XML= XML::Twig->new(
    twig_handlers => { 
     q{project[@path =~ /\bopensource\b/]} => \&read_version_into_hash, 
    }, 
    pretty_print => 'indented', 
); 
$DEFAULT_XML = 'default.xml' if !($DEFAULT_XML); 
$VERSIONED_XML = 'versioned.xml' if !($VERSIONED_XML); 
$REF_XML->parsefile($VERSIONED_XML); 
#using "parsefile_inplace" is making default.xml as 0 byte. 
$UPDATE_XML->parsefile_inplace($DEFAULT_XML); 
#below print works good 
#$UPDATE_XML->parsefile($DEFAULT_XML); 
#$UPDATE_XML->print; 
sub read_version_into_hash 
{ 
    my ($twig, $project) = @_; 
    $project->set_att(
     revision => $project->{att}{revision}, 
    ); 
     $VERSION_HASH{$project->{att}{path}}=$project->{att}{revision}; 
} 
sub fix_opensource_revision { 
    my ($twig, $project) = @_; 

    if ($VERSION_HASH{$project->{att}{path}}) 
    { 
     $project->set_att(
     revision => $VERSION_HASH{$project->{att}{path}}, 
     ); 
    } 
    else 
    { 
     die "No revision found for $project->{att}{path}\n"; 
    } 
} 
sub update_default_branch_name { 
    my ($twig, $default) = @_; 
    $default->set_att(
     revision => $BRANCH_NAME, 
     ); 
    } 
sub remove_revision_attribute { 
    my ($twig, $project) = @_; 
    $project->del_att(
     'revision' 
     ); 
    } 
sub fix_docs_to_master { 
    my ($twig, $project) = @_; 
    $project->set_att(
     revision => 'master', 
     ); 
} 

上面的腳本將default.xml作爲0kb文件,其中在屏幕上的打印效果很好。Perl小枝,從一個xml中獲取屬性值並更新其他

default.xml中片斷

<project path="LINUX/opensource/utils" revision="apple" name="le/utils" x-ship="oss" x-quic-dist="le"/> 

versioned.xml片斷

<project path="LINUX/opensource/utils" revision="e10616sggf012"/> 

也請讓我知道如果我能做些什麼來減少代碼的行數。

+1

小錯誤:

把它應用到您的處理程序中,只有一個代碼' 「versionedxml = S」=> \&VERSIONED_XML,'。將'&'更改爲'$'。另外,你可以通過在裏面包含'my'來簡化你的參數聲明。完整修正:''versionedxml = s「=> \ my $ VERSIONED_XML,' – Miller

+1

'sub-read_version_into_hash'中的無關代碼。你正在給自己分配屬性。可以刪除它。 – Miller

回答

2

查閱以下文檔:XML::Twig - Processing an XML document chunk by chunk。顯然,你需要在你的任何處理程序中調用flush,以表明你在任何時候進行了就地操作。

我將此技術應用到您發佈的上一個線索中的數據:Updating xml attribute value based on other with Perl並且它似乎可行。這條線

sub update_default_branch_name { 
    my ($twig, $default) = @_; 
    $default->set_att(revision => $BRANCH_NAME); 
    $twig->flush; 
} 
+0

非常感謝Miller,除了「sub fix_docs_to_master」,我希望將path =「LINUX/docs」添加到line =「master」,但它在以下行中添加了,這是一個結束標記這整個XML,如:<項目名稱=「專有/ docs」路徑=「LINUX/docs」x-ship =「none」/> – rodee

+0

添加「| docs」不清除修訂標記如果路徑有「文檔「解決了這個問題,我編輯爲:q {project [@path!〜/ \ bopensource | docs \ b /]} => \&remove_revision_attribute – rodee