user2223335
user2223335

Reputation: 209

XML file creation in Perl

My input file is

TBLA      COLA      A    B    
TBLA      COLB      D    E    
TBLB      COLX      M    N     
TBLB      COLD      A    B   
TBLC      COLD      A    B 

The output to be created in xml format as

<Data>    
    <TBLA>    
        <COLA>
            <oldvalue>A</oldvalue>
            <newvalue>B</newvalue>    
        </COLA>         
        <COLB>    
            <oldvalue>D</oldvalue>    
            <newvalue>E</newvalue>     
        </COLB>       
    </TBLA>    
    <TBLB>     
        <COLX>    
            <oldvalue>M</oldvalue>    
            <newvalue>N</newvalue>    
        </COLX>       
        <COLD>    
            <oldvalue>A</oldvalue>   
            <newvalue>B</newvalue>     
        </COLD>       
    </TBLB>     
    <TBLC>    
        <COLD>    
            <oldvalue>A</oldvalue>    
            <newvalue>B</newvalue>     
        </COLD>   
    </TBLC>  
</Data>     

Can anyone suggest what would be the best way to do this. Should i convert this text file to hash of hashes first and then try using pltoxml(). does this make sense. Can XML::Simple or XML::Writer suffice this.

This is the first time I am working on xml and not sure which approach will help efficicently my solution.
A small example wrt to my req would be appreciated.

*Input file will always be sorted on first field

Upvotes: 2

Views: 126

Answers (2)

user1558455
user1558455

Reputation:

Recommend is to use XML::Simple instead of writing an selfmade XML Parser. You just need to set:

use XML::Simple;
my $xml = XMLout($hashref, RootName => 'Data');

Upvotes: 1

amon
amon

Reputation: 57600

Given the very simple data structure, It seems a bit unneccessary to use a whole XML writer. However, I'll assume that that the table and column names are valid XML tag names.

Here is a simple script that reads through the data without storing it in an intermediary data structure. It works with perl5 v10 and better.

use strict; use warnings; use feature 'say';

my $last_table;
say '<Data>';
while(<>) {
  chomp;
  my ($table, $col, $old, $new) = split /\t/;
  s/&/&amp;/g, s/</&lt;/g for $old, $new;
  # I'll assume $table and $col have sane names
  if (not defined $last_table) {
    say "  <$table>";
  } elsif ($last_table ne $table) {
    say "  </$last_table>";
    say "  <$table>";
  }
  $last_table = $table;
  say "    <$col>";
  say "      <oldvalue>$old</oldvalue>";
  say "      <newvalue>$new</newvalue>";
  say "    </$col>";
}
say "  </$last_table> if defined $last_table;
say '</Data>';

Upvotes: 2

Related Questions