Venkatesh
Venkatesh

Reputation: 303

formatted text to XML (or) JSON using perl

I need to parse formatted text to XML using Perl. It is .cfg file which contains formatted text.

Some part of file ::

system
    name "NILpv-BNG34"
    contact "Wayne Ritchie/NGN OPERATIONS 0800 4 NGNOP (0800 464 667)"
    location "NIL, Level 1, Tory Street, Wellington."
    clli-code "BNG_v15    "
    chassis-mode c
    dns
    exit
    persistence
        subscriber-mgmt
            location cf2:
        exit
    exit
    snmp
        streaming
            no shutdown
        exit
        packet-size 9216
    exit
    time
        ntp
            server 10.78.247.155 prefer
            no shutdown
        exit
        sntp
            shutdown
        exit
        dst-zone NZDT
            start last sunday september 02:00
            end first sunday april 03:00
        exit
        zone NZST 
    exit
    thresholds
        rmon
        exit
    exit
exit

All the text in file is formatted with 4 spaces and exit.

I thought of changing above text to

<?xml version="1.0" encoding="UTF-8"?>
<system>
    <name>"WR-BNG01"</name>
    <contact>"NGN OPERATIONS 0800 4 NGNOP (0800 464667)"</contact>
    <location>"Whangarei Telephone exchange"</location>
    <clli-code>"BNG_v4 "</clli-code>
    <chassis-mode>c</chassis-mode>
    <dns />
    <persistence>
        <subscriber-mgmt>
            <location>cf2:</location>
        </subscriber-mgmt>
    </persistence>
    <snmp>
        <packet-size>9216</packet-size>
    </snmp>
    <time>
        <ntp>
            <server>10.72.14.17</server>
            <server>10.74.14.26 prefer</server>
            <no>shutdown</no>
        </ntp>
        <sntp>
            <shutdown />
        </sntp>
        <dst-zone_NZDT>
            <start>last sunday september 02:00</start>
            <end>first sunday april 03:00</end>
        </dst-zone_NZDT>
        <zone>NZST</zone>
    </time>
    <thresholds>
        <rmon />
    </thresholds>
</system>

I wrote a Perl script for this but it does not work in some cases.

cpu-protection
            policy 1 create
            exit
            policy 254 create
            exit
            policy 255 create
            exit
        exit

Here, XML becomes

<cpu-protection>
        <policy>1 create</policy>
        <policy>254 create</policy>
        <policy>255 create</policy>
</cpu-protection>

instead of

<cpu-protection>
        <policy_1_create></policy_1_create>
        <policy_254_create></policy_254_create>
        <policy_255_create></policy_255_create>
</cpu-protection>

My script (Part for changing data to XML) ::

    foreach my $i ( 1 .. $index ) {
    @grabbed = @grabbed_1 if $i == 1;
    @grabbed = @grabbed_2 if $i == 2;

    my $currentLine;

    my $previousLineSpaceLength = 0;
    my $currentLineSpaceLength  = 0;
    my $nextLineSpaceLength     = 0;

    my @exitTags;
    my $exitTag = '';

    my @tag;
    my $lineSplits;

    my $xmlString = '<?xml version="1.0" encoding="UTF-8"?>';
    foreach my $i ( 0 .. $#grabbed ) {

        $currentLine = $grabbed[$i];
        $currentLine =~ /^\s*/;
        $currentLineSpaceLength = $+[0];

        chomp($currentLine);
        $currentLine =~ s/^\s+//;
        $currentLine =~ s/\s+$//;

        #$currentLine =~ s/"//g;

        @tag = split ' ', $currentLine, 2;
        $lineSplits = scalar @tag;

        if ( $previousLineSpaceLength == 0 ) {

            $previousLineSpaceLength = $currentLineSpaceLength;

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

          #$xmlString               = $xmlString . '<' . $currentLine . '>';
          #$exitTag                 = '</' . $currentLine . '>';

        }
        elsif ($currentLineSpaceLength > $previousLineSpaceLength
            && $exitTag ne '' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            push @exitTags, $exitTag;

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

            #$xmlString = $xmlString . '<' . $currentLine . '>';
            #$exitTag   = '</' . $currentLine . '>';
        }
        elsif ($currentLineSpaceLength == $previousLineSpaceLength
            && $currentLine ne 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            if ( $exitTag ne 'exit' ) {
                $xmlString = $xmlString . $exitTag;

            }

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

            #$xmlString = $xmlString . '<' . $currentLine . '>';
            #$exitTag   = '</' . $currentLine . '>';

        }
        elsif ($currentLineSpaceLength == $previousLineSpaceLength
            && $currentLine eq 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            $xmlString               = $xmlString . $exitTag;
            $exitTag                 = $currentLine;

        }
        elsif ($currentLineSpaceLength < $previousLineSpaceLength
            && $currentLine eq 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            if ( $exitTag ne 'exit' ) {
                $xmlString = $xmlString . $exitTag;

            }
            $xmlString = $xmlString . pop @exitTags;
            $exitTag   = $currentLine;
        }

    }

    push @XMLStrings, $xmlString;

 }

Please help with corrections required.

Full Code ::

#!/usr/bin/perl

use Data::Dumper;
use XML::XPath;
use XML::DOM;

my $file1 = "1.cfg";
my $file2 = "2.cfg";

my @configFiles = ( $file1, $file2 );

my $templateFile = "template.cfg";
my @configModules;
my %configurationsHash;
my $configName;

open( TEMPLATE, "<" . $templateFile ) or die "cannot open file";
while (<TEMPLATE>) {
    chomp($_);
    push @configModules, $_ if /^[[:alpha:]]/;
$configName = $_ if /^[[:alpha:]]/;
push @{ $configurationsHash{$configName} }, $_ if /^\//;
}
close(TEMPLATE);

foreach $configSubModule (@configModules) {
chomp($configSubModule);

my $index = 0;
my @grabbed_1;
my @grabbed_2;

foreach my $file (@configFiles) {
    my $last = 0, $end = 0;
    $index++;

    open( CONFIGFILE, "<" . $file );
    while (<CONFIGFILE>) {
        if (/$configSubModule/) {
            while (<CONFIGFILE>) {
                if (/#---/) {
                    $end = 1, last if $last;
                    $last = 1;
                }
                else {
                    push @grabbed_1, $_ if $index == 1;
                    push @grabbed_2, $_ if $index == 2;
                }
            }
        }
        last if $end;
    }
}

    my @grabbed;
    my @XMLStrings;

    foreach my $i ( 1 .. $index ) {
    @grabbed = @grabbed_1 if $i == 1;
    @grabbed = @grabbed_2 if $i == 2;

    my $currentLine;

    my $previousLineSpaceLength = 0;
    my $currentLineSpaceLength  = 0;
    my $nextLineSpaceLength     = 0;

    my @exitTags;
    my $exitTag = '';

    my @tag;
    my $lineSplits;

    my $xmlString = '<?xml version="1.0" encoding="UTF-8"?>';
    foreach my $i ( 0 .. $#grabbed ) {

        $currentLine = $grabbed[$i];
        $currentLine =~ /^\s*/;
        $currentLineSpaceLength = $+[0];

        chomp($currentLine);
        $currentLine =~ s/^\s+//;
        $currentLine =~ s/\s+$//;

        #$currentLine =~ s/"//g;

        @tag = split ' ', $currentLine, 2;
        $lineSplits = scalar @tag;

        if ( $previousLineSpaceLength == 0 ) {

            $previousLineSpaceLength = $currentLineSpaceLength;

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

          #$xmlString               = $xmlString . '<' . $currentLine . '>';
          #$exitTag                 = '</' . $currentLine . '>';

        }
        elsif ($currentLineSpaceLength > $previousLineSpaceLength
            && $exitTag ne '' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            push @exitTags, $exitTag;

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

            #$xmlString = $xmlString . '<' . $currentLine . '>';
            #$exitTag   = '</' . $currentLine . '>';
        }
        elsif ($currentLineSpaceLength == $previousLineSpaceLength
            && $currentLine ne 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            if ( $exitTag ne 'exit' ) {
                $xmlString = $xmlString . $exitTag;

            }

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                $exitTag   = '</' . $currentLine . '>';
            }
            elsif ( $lineSplits == 2 ) {

                $nextLine = $grabbed[ $i + 1 ];
                $nextLine =~ /^\s*/;
                $nextLineSpaceLength = $+[0];

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString =
                      $xmlString . '<' . $tag[0] . '_' . $tag[1] . '>';
                    $exitTag = '</' . $tag[0] . '_' . $tag[1] . '>';

                }
                else {
                    $xmlString = $xmlString . '<' . $tag[0] . '>' . $tag[1];
                    $exitTag   = '</' . $tag[0] . '>';
                }

            }

            #$xmlString = $xmlString . '<' . $currentLine . '>';
            #$exitTag   = '</' . $currentLine . '>';

        }
        elsif ($currentLineSpaceLength == $previousLineSpaceLength
            && $currentLine eq 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            $xmlString               = $xmlString . $exitTag;
            $exitTag                 = $currentLine;

        }
        elsif ($currentLineSpaceLength < $previousLineSpaceLength
            && $currentLine eq 'exit' )
        {
            $previousLineSpaceLength = $currentLineSpaceLength;
            if ( $exitTag ne 'exit' ) {
                $xmlString = $xmlString . $exitTag;

            }
            $xmlString = $xmlString . pop @exitTags;
            $exitTag   = $currentLine;
        }

    }

    push @XMLStrings, $xmlString;

}

print "\n", 'Configuration :: ', $configSubModule, "\n";

foreach my $path ( @{ $configurationsHash{$configSubModule} } ) {

    $path =~ s/\s+/_/g;

    print $path;
    my $XMLIndex = 0;

    my @XMLOne;
    my @XMLTwo;

    foreach my $xml (@XMLStrings) {

        $XMLIndex++;
        $xp = XML::XPath->new($xml);

        if ( $xp->find($path) ) {
            my $nodeset  = $xp->find($path);
            my @nodeList = $nodeset->get_nodelist;

            foreach my $node (@nodeList) {
                my @childNodes = $node->getChildNodes;
                foreach my $childNode (@childNodes) {
                    print "\n", $childNode->getName;
                }
            }
        }
        else {
            print $path, ' =>  Not Available in file : ' . $XMLIndex, "\n";
        }
        print "\n";
    }

}

}

Need to compare two .cfg files and show differences.

required pattern is taken from another file.

System Configuration
#/system
#/system/persistence
/system/snmp/streaming
/system/time
#/system/time/ntp
#/system/time/sntp
/system/time/dst-zone NZDT
#/system/thresholds

System Security Configuration
#/system
#/system/security
#/system/security/management-access-filter
#/system/security/management-access-filter/ip-filter

Upvotes: 0

Views: 88

Answers (3)

Venkatesh
Venkatesh

Reputation: 303

Converts data to XML to compare and display differences.

#!/usr/bin/perl

use strict;
use warnings;
use XML::XPath;

use Data::Dumper;

my $exitProgram = 0;

if ( @ARGV != 3 ) {
    print "Proper Files input required !!\n";
    exit;
}

if ( !-e $ARGV[0] ) {
    print "Template File Not found!!\n";
    $exitProgram = 1;
}

if ( !-e $ARGV[1] ) {
    print "Test File Not found!!\n";
    $exitProgram = 1;
}

if ( !-e $ARGV[2] ) {
    print "Production File Not found!!\n";
    $exitProgram = 1;
}

exit 101 if $exitProgram;

if ( -z $ARGV[0] ) {
    print "Template File Empty!!\n";
    $exitProgram = 1;
}

if ( -z $ARGV[1] ) {
    print "Test File Empty!!\n";
    $exitProgram = 1;
}

if ( -z $ARGV[2] ) {
    print "Production File Empty!!\n";
    $exitProgram = 1;
}

exit 102 if $exitProgram;

my $templateFile = $ARGV[0];
my $test         = $ARGV[1];
my $prod         = $ARGV[2];

my @configFiles = ( $test, $prod );

my @addrootElementAppendRequired = (
    'Switch Fabric Configuration',
    'Card Configuration',
    'Port Configuration',
    'LAG Configuration'
);    

 my @configModules;
 my %configurationsHash;
 my $configName;

open( TEMPLATE, "<" . $templateFile ) or die "cannot open file";
while (<TEMPLATE>) {
    chomp($_);
    push @configModules, $_ if /^[[:alpha:]]/;
    $configName = $_ if /^[[:alpha:]]/;
    push @{ $configurationsHash{$configName} }, $_ if /^\|/;
}  
close(TEMPLATE);

if ( scalar @configModules == 0 ) {
    print "Configuration modules not specefied in Template File\n";
    exit 103;
}

=pod

if( scalar %configurationsHash == 0 ){
    print "Configuration Hierarchy not specefied in Template File\n";
    exit 103;
}

=cut

my $configSubModuleEscaped;

foreach my $configSubModule (@configModules) {
chomp($configSubModule);

print "\nConfiguration :: $configSubModule\n";

$configSubModuleEscaped = quotemeta '"' . $configSubModule . '"';

my $index = 0;
my @grabbed_1;
my @grabbed_2;
my $last = 0;
my $end  = 0;

foreach my $file (@configFiles) {
    $last = 0;
    $end  = 0;
    $index++;

    open( CONFIGFILE, "<" . $file );
    while (<CONFIGFILE>) {
        if (/$configSubModuleEscaped/) {
            while (<CONFIGFILE>) {
                if (/#---/) {
                    $end = 1, last if $last;
                    $last = 1;
                }
                else {
                    push @grabbed_1, $_ if $index == 1;
                    push @grabbed_2, $_ if $index == 2;
                }
            }
        }
        last if $end;
    }
}

my @grabbed;
my @XMLStrings;

foreach my $i ( 1 .. $index ) {
    @grabbed = @grabbed_1 if $i == 1;
    @grabbed = @grabbed_2 if $i == 2;

    my $currentLine;

    my $previousLineSpaceLength = 0;
    my $currentLineSpaceLength  = 0;
    my $nextLineSpaceLength     = 0;

    my @exitTags;
    my $exitTag = '';

    my @tag;
    my $lineSplits;

    my $xmlString = '';
    foreach my $i ( 0 .. $#grabbed ) {

        $currentLine = $grabbed[$i];
        $currentLine =~ /^\s*/;
        $currentLineSpaceLength = $+[0];
        chomp($currentLine);
        $currentLine =~ s/^\s+//;
        $currentLine =~ s/\s+$//;

        @tag = split ' ', $currentLine, 2;
        $lineSplits = scalar @tag;

        ## If configuration has single line.
        if ( ( scalar @grabbed ) == 1 ) {
            $xmlString = '<' . $tag[0] . '/>' if $lineSplits == 1;
            $xmlString =
              '<' . $tag[0] . ' id=\'' . $tag[1] . '></' . $tag[0] . '>'
              if $lineSplits == 2;
            next;
        }

        if ( $previousLineSpaceLength == 0 ) {

            if ( $lineSplits == 1 ) {
                $xmlString = $xmlString . '<' . $currentLine . '>';
                push @exitTags, '</' . $currentLine . '>';
            }
            else {
                $xmlString =
                  $xmlString . '<' . $tag[0] . ' id=\'' . $tag[1] . '\'>';
                push @exitTags, '</' . $tag[0] . '>';
            }
        }
        elsif ( $currentLineSpaceLength > $previousLineSpaceLength ) {
            my $nextLine = $grabbed[ $i + 1 ];
            $nextLine =~ /^\s*/;
            $nextLineSpaceLength = $+[0];
            chomp($nextLine);
            $nextLine =~ s/^\s+//;
            $nextLine =~ s/\s+$//;

            if ( $lineSplits == 1 ) {
                if ( $nextLineSpaceLength <= $currentLineSpaceLength ) {
                    $xmlString = $xmlString . '<' . $currentLine . ' />';
                }
                else {
                    $xmlString = $xmlString . '<' . $currentLine . '>';
                    push @exitTags, '</' . $currentLine . '>';
                }
            }
            elsif ( $lineSplits == 2 ) {
                if ( $nextLineSpaceLength <= $currentLineSpaceLength ) {
                    $xmlString =
                        $xmlString . '<'
                      . $tag[0] . '>'
                      . $tag[1] . '</'
                      . $tag[0] . '>';
                }
                else {
                    $xmlString =
                        $xmlString . '<'
                      . $tag[0]
                      . ' id=\''
                      . $tag[1] . '\'>';
                    push @exitTags, '</' . $tag[0] . '>';
                }
            }

        }
        elsif ( ( $currentLineSpaceLength == $previousLineSpaceLength )
            && $currentLine ne 'exit' )
        {
            my $nextLine = $grabbed[ $i + 1 ];
            $nextLine =~ /^\s*/;
            $nextLineSpaceLength = $+[0];
            chomp($nextLine);
            $nextLine =~ s/^\s+//;
            $nextLine =~ s/\s+$//;
            if ( $lineSplits == 1 ) {

                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {
                    $xmlString = $xmlString . '<' . $currentLine . '>';
                    push @exitTags, '</' . $currentLine . '>';
                }
                else {
                    $xmlString = $xmlString . '<' . $currentLine . ' />';
                }

            }
            elsif ( $lineSplits == 2 ) {
                if ( $nextLineSpaceLength > $currentLineSpaceLength ) {

                    $xmlString =
                        $xmlString . '<'
                      . $tag[0]
                      . ' id=\''
                      . $tag[1] . '\'>';
                    push @exitTags, '</' . $tag[0] . '>';
                }
                else {
                    if ( ( $currentLineSpaceLength == $nextLineSpaceLength )
                        && $nextLine eq 'exit' )
                    {
                        $xmlString =
                            $xmlString . '<'
                          . $tag[0]
                          . ' id=\''
                          . $tag[1] . '\'>' . '</'
                          . $tag[0] . '>';

                    }
                    else {
                        $xmlString =
                            $xmlString . '<'
                          . $tag[0] . '>'
                          . $tag[1] . '</'
                          . $tag[0] . '>';
                    }
                }
            }

        }
        elsif ( ( $currentLineSpaceLength < $previousLineSpaceLength )
            && $currentLine eq 'exit' )
        {
            $xmlString = $xmlString . pop @exitTags;
        }

        $previousLineSpaceLength = $currentLineSpaceLength;

    }

    if ( grep { $_ eq $configSubModule } @addrootElementAppendRequired ) {
        my $subModuleTemp = $configSubModule;
        $subModuleTemp =~ s/ /_/g;
        $xmlString = '<'
          . $subModuleTemp . '>'
          . $xmlString . '</'
          . $subModuleTemp . '>';

    }
    $xmlString = '<?xml version="1.0" encoding="UTF-8"?>' . $xmlString;
    push @XMLStrings, $xmlString;

}

my $matched;
my @ary;
my %params;

foreach my $path ( @{ $configurationsHash{$configSubModule} } ) {
    $matched = 1;

    print "\nHierarchy : $path\n";

    @ary = split '\|', $path;
    foreach my $i ( 1 .. $#ary ) {
        my @splits = split ' ', $ary[$i], 2;
        if ( ( scalar @splits ) == 2 ) {
            my $tmp      = $ary[$i];
            my $withAttr = $splits[0] . '[@id=\'' . $splits[1] . '\']';
            $path =~ s/$tmp/$withAttr/;
        }
    }

    $path =~ s/\|/\//g;
    if ( grep { $_ eq $configSubModule } @addrootElementAppendRequired ) {
        my $subModuleTemp = $configSubModule;
        $subModuleTemp =~ s/ /_/g;
        $path = '/' . $subModuleTemp . $path;
    }

    my $XMLIndex = 0;
    my @test;
    my @prod;
    my $nodeset;
    my @nodeList;
    my $nodeString;
    my $node;
    my @childNodes;
    my $stringToPush;
    my $xp;
    my $checkInProduction = 1;

    foreach my $xml (@XMLStrings) {

        $XMLIndex++;
        $xp = XML::XPath->new($xml);
        if ( $xp->find($path) ) {

            @nodeList = $xp->findnodes($path);

            my @chn;
            for my $node (@nodeList) {
                @chn = $node->getChildNodes;
                my $childCount = 0;
                foreach my $n (@chn) {
                    $childCount++ if $n->getNodeType == 1;
                }

                if ( $childCount == 0 ) {
                    $stringToPush = $node->string_value;
                    push @test, $stringToPush
                      if $XMLIndex == 1;
                    push @prod, $stringToPush
                      if $XMLIndex == 2;
                }
                elsif ( $childCount >= 1 ) {
                    foreach my $n (@chn) {
                        if ( $n->getNodeType == 1 ) {
                            $stringToPush = $n->getName;
                            $stringToPush =
                              $stringToPush . ' ' . $n->getAttribute('id')
                              if defined $n->getAttribute('id');
                            $stringToPush =
                              $stringToPush . ' ' . $n->string_value
                              if $n->getName eq 'no';
                            push @test, $stringToPush if $XMLIndex == 1;
                            push @prod, $stringToPush if $XMLIndex == 2;
                        }
                    }
                }
            }
        }
        else {
            $matched = 0;
            print 'Does not exist ';
            print "Test\n" if $XMLIndex == 1;
            $checkInProduction = 0 if $XMLIndex == 2;
            print "Production\n" if $XMLIndex == 2;
        }
    }

    %params = map { $_ => 1 } @prod;
    foreach my $var (@test) {
        last if !$checkInProduction;
        if ( !exists( $params{$var} ) ) {
            $matched = 0;
            print $var . " => Not in Production\n" if $var ne '';
        }
    }

    %params = map { $_ => 1 } @test;
    foreach my $var (@prod) {
        if ( !exists( $params{$var} ) ) {
            $matched = 0;
            print $var . " => Not in Test\n" if $var ne '';
        }
    }
    print "Matched\n" if $matched;
}
}

Upvotes: 0

Jeremy Jones
Jeremy Jones

Reputation: 5631

Another option, if you can rely on the data

#!/usr/bin/perl -l
use warnings;
use strict;

my @tags = ();

print qq[<?xml version="1.0" encoding="UTF-8"?>\n];

while (<DATA>) {
    chomp;
    s/^\s+//;

    if (@tags and $_ eq 'exit') {
        print sprintf("%s</%s>", (" " x (scalar(@tags)-1)), pop @tags);
    }
    else {
        tr/a-zA-Z0-9-/_/cs;
        print sprintf("%s<%s>", (" " x scalar(@tags)), $_);
        push @tags, $_;
    }
}

__DATA__
cpu-protection
        policy 1 create
        exit
        policy 254 create
        exit
        policy 255 create
        exit
    exit

Output

$ perl script3.pl
<?xml version="1.0" encoding="UTF-8"?>

<cpu-protection>
 <policy_1_create>
 </policy_1_create>
 <policy_254_create>
 </policy_254_create>
 <policy_255_create>
 </policy_255_create>
</cpu-protection>
$ 

Upvotes: 0

Borodin
Borodin

Reputation: 126732

I recommend the XML::Writer for this. It will keep track of the stack of outstanding open tags that remain to be closed

It would look like this

use strict;
use warnings;

use XML::Writer;

my $writer = XML::Writer->new( DATA_MODE => 1, DATA_INDENT => '  ');

$writer->xmlDecl('UTF-8');

while ( <DATA> ) {

  next unless /^(\s*)(\S.*\S*)/;

  my $tag = $2 =~ tr/ /_/r;

  if ( $tag eq 'exit' ) {
    $writer->endTag;
  }
  else {
    $writer->startTag($tag);
  }
}

$writer->end;

__DATA__
cpu-protection
        policy 1 create
        exit
        policy 254 create
        exit
        policy 255 create
        exit
    exit

output

<?xml version="1.0" encoding="UTF-8"?>

<cpu-protection>
  <policy_1_create></policy_1_create>
  <policy_254_create></policy_254_create>
  <policy_255_create></policy_255_create>
</cpu-protection>

Upvotes: 2

Related Questions