【问题标题】:How to search and replace xml snippet using perl code如何使用 perl 代码搜索和替换 xml 片段
【发布时间】:2013-12-10 18:13:10
【问题描述】:

我在一个文件中有这个 xml 代码 sn-p,我想使用 perl 将其注释掉。

<plugin id="InvalidObjectsCheck"
        description="Verifying No Database Invalid Objects Exist"
        invoke=""
        plugin.class="oracle.check.apps.InvalidObjectsCheckPlugin"
        class.path="$HC_LOCATION/lib/precheckplugin.jar;
                    $HC_LOCATION/lib/hccommon.jar;
                    $APPLICATIONS_BASE/fusionapps/applications/lcm/ad/java/adjava.jar"
        stoponerror="false"/>

不幸的是,其他 DTD 的结束标记 (stoponerror="false"/>) 也是如此。我为此编写了一个子例程,但不知道在读取文件的全部内容后如何继续。

sub skip_lp_hc($skiplphc)
    {
        $hcfile = "${sharedStorageLoc}${fs}${podName}${fs}${releaseTo}${fs}fusionapps${fs}applications${fs}lcm${fs}hc${fs}config${fs}ga${fs}GeneralSystemHealthChecks.xml";
        if(! -e "$hcfile")
        {
            print "[ERROR]: Unable to locate the manifest file : GeneralSystemHealthChecks.xml\n";
            print "[INFO] : Located at ${sharedStorageLoc}${fs}${podName}${fs}${releaseTo}${fs}fusionapps${fs}applications${fs}lcm${fs}hc${fs}config${fs}ga\n";
        }
        if($skiplphc eq true)
        {
            print "[SUCCESS] : Able to access GeneralSystemHealthChecks.xml\n";
            print "[INFO] : ${sharedStorageLoc}${fs}${podName}${fs}${releaseTo}${fs}fusionapps${fs}applications${fs}lcm${fs}hc${fs}config${fs}ga\n";
            open (IN, "<$hcfile") or die "Cannot open the file : $hcfile\n";
            while (my $my_line = <IN> )
                {
                        chomp $my_line;
                        $my_line =~ s/^\s+//;
                        $my_line =~ s/\s+$//;
                        if ($my_line =~ m/<plugin id="InvalidObjectsCheck"\=(.*)/)
                        {
                          print "[INFO] : Found a match for <plugin id=InvalidObjectsCheck            after accessing GeneralSystemHealthChecks.xml\n";
                        }
                }
                close (IN);
        }
    }

【问题讨论】:

  • 我假设${fs} 是您的“字段分隔符”?这不是很可读。您应该考虑改用join。或者,如果这是您正在处理的路径,请使用适当的模块,例如来自 File::Speccatfile
  • 请把缺少的动词填入很遗憾,其他DTD的结束标记(stoponerror="false"/>)也是
  • 另外:if($skiplphc eq true) 是一种检查真实值的可怕方法。 if ($skip) 是您所需要的,使用 eq 将使检查更加严格。你已经宣布你的子程序非常错误,sub skip_lp_hc($skiplphc) { 应该是sub skip_lp_hc { my ($skip_lp_hc) = @_;

标签: xml perl


【解决方案1】:

我会让你处理疯狂的文件名,并给你一个简单的基于 XML::Twig 的解决方案,让你远离 XML-parsing-with-regexp Hell:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { plugin => \&plugin }, # process only plugin
                twig_print_outside_roots => 1,        # output rest unchanged
                pretty_print => 'cvs',                # closest style to input
              )
         ->parsefile_inplace( "my.xml");

# called for each plugin element
sub plugin
  { my( $t, $plugin)=@_;
    my $text= $plugin->sprint;
    $text=~ s{;   }{;\n}g;      # slightly massage the output to get proper format
    print "<!--$text\n  -->";   # output element commented out
  }

有了这个,您无需担心初始 XML 的细节,甚至无需读取内存中的整个文件。

【讨论】:

    【解决方案2】:

    ${sharedStorageLoc} 是 shell 语法,请在 perl 文件中使用 $sharedStorageLoc。

    if($skiplphc eq true) 是 shell 语法,请改用 if($skiplphc)。

    sub skip_lp_hc($skiplphc) 也不是一个好的 perl 语法。

    我认为你真正的问题是你的正则表达式,它有一个额外的 = 并且它不匹配。

    我改写了一下:

    sub skip_lp_hc {
      my $skiplphc = shift;
      my $hcfile = "$sharedStorageLoc$fs$podName$fs$releaseTo$fsfusionapps$fs$applications$fs$lcm$fs$hc$fs$config$fs$ga$fs$GeneralSystemHealthChecks.xml";
      if(! -e "$hcfile") {
         print "[ERROR]: Unable to locate the manifest file : GeneralSystemHealthChecks.xml\n";
         print "[INFO] : Located at $sharedStorageLoc$fs$podName$fs$releaseTo$fsfusionapps$fs$applications$fs$lcm$fs$hc$fs$config$fs$ga\n";
      }
      if($skiplphc)  {
         print "[SUCCESS] : Able to access GeneralSystemHealthChecks.xml\n";
         print "[INFO] : $sharedStorageLoc$fs$podName$fs$releaseTo$fsfusionapps$fs$applications$fs$lcm$fs$hc$fs$config$fs$ga\n";
         open (IN, "<", $hcfile) or die "Cannot open the file : $hcfile, $!\n";
         while (my $my_line = <IN> )  {
                 chomp $my_line;
                 $my_line =~ s/^\s+//s;
                 $my_line =~ s/\s+$//s;
                 if ($my_line =~ m/<plugin\s+id=['"]InvalidObjectsCheck/i){
                     print "[INFO] : Found a match for <plugin id=InvalidObjectsCheck after accessing GeneralSystemHealthChecks.xml\n";
                 }
             }
             close (IN);
      }
    }
    

    【讨论】:

    • ${sharedStorageLoc} 是有效的 Perl 语法。您可以使用花括号来消除歧义。这:$fsfusionapps 不插入 $fs 变量,例如,需要为 ${fs}fusionapps
    • 我知道,但每次使用都不会太失败。这就是为什么我说它是一个类似于 shell 的语法......
    猜你喜欢
    • 2015-08-01
    • 1970-01-01
    • 2013-05-20
    • 2019-05-05
    • 1970-01-01
    • 2017-01-03
    • 2017-01-05
    • 2018-08-21
    • 2010-10-29
    相关资源
    最近更新 更多