Reputation: 303
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
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
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
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
<?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