analys has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm using xml::writer trying to output the xml file from the csv input file. I'm not sure how to print the name as a separate tag.
#input file name subname start size CAL_M reserved 0 13 CAL_M o_check_out 13 7 CAL_M o_ttr_first 20 4 CAL_M o_cal_check_1 24 4 PSQN_0 reserved 0 8 PSQN_0 check_final 8 10 PSQN_0 o_check 18 10
#expected output file <structure name="CAL_M"> <value type = "13"name = "reserved" start = "0" </value> <value type = "7" name = "o_check_out" start = "13"</value> <value type = "4" name = "o_ttr_first" start = "20"</value> <value type = "4" name = "o_cal_check_1"start = "24"</value> </structure> <structure name="PSQN_0"> <value type = "8" name = "reserved" start = "0" </value> <value type = "10" name = "check_final"start = "8"</value> <value type = "10" name = "o_check" start = "18" </value> </structure>
#current output file <value type = "13"name = "reserved" start = "0" </value> <value type = "7" name = "o_check_out" start = "13"</value> <value type = "4" name = "o_ttr_first" start = "20"</value> <value type = "4" name = "o_cal_check_1"start = "24"</value> <value type = "8" name = "reserved" start = "0" </value> <value type = "10" name = "check_final"start = "8"</value> <value type = "10" name = "o_check" start = "18" </value>
Here's my code
#input file open (FILE,"<in.csv") || die "cannot open file: $!"; my @array =<FILE>; close (FILE); #output file my $output_file = "myfile.xml"; my $output = new IO::File(">$output_file"); my $writer = new XML::Writer(OUTPUT=>$output, DATA_MODE=>1, DATA_INDEN +T => 2); #structure foreach my $item(@array) { chomp($item); $item =~/(\w+),(\w+),(\d+),(\d+)/; my $name =$1; my $sname=$2; my $start=$3; my $size =$4; $writer->startTag("structure", "name"=>$name); $writer->startTag("value", "type"=>$size, "name"=>$sname, "start"= +>$start); $writer->endTag(); $writer->endTag(); } $writer->end(); $output->close();

Replies are listed 'Best First'.
Re: perl writing to xml file (xml::writer)
by choroba (Cardinal) on Feb 02, 2016 at 17:13 UTC
    Remember the name of the structure in a variable, start a new structure only when the current name is different.

    I also fixed the code in order to be able to run it with the data you showed (no commas, no root node) and without creating any files. Adapt to your desires as needed.

    #!/usr/bin/perl use warnings; use strict; use XML::Writer; my @array = split /\n/, << '__CSV__'; name subname start size CAL_M reserved 0 13 CAL_M o_check_out 13 7 CAL_M o_ttr_first 20 4 CAL_M o_cal_check_1 24 4 PSQN_0 reserved 0 8 PSQN_0 check_final 8 10 PSQN_0 o_check 18 10 __CSV__ my $writer = 'XML::Writer'->new( DATA_MODE => 1, DATA_INDENT => 2); $writer->startTag('root'); my $prev_name = q(); for my $item(@array) { chomp $item; if (my ($name, $sname, $start, $size) = $item =~/(\w+)\s+(\w+)\s+( +\d+)\s+(\d+)/) { if ($prev_name ne $name) { if ($prev_name) { $writer->endTag('structure'); } $writer->startTag('structure', name => $name); } $writer->startTag('value', type => $size, name => $sname, start => $start, ); $writer->endTag('value'); $prev_name = $name; } } $writer->endTag($_) for qw( structure root ); $writer->end;
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      thanks choroba. btw, what does this actually do? my $prev_name = q(); is it the same as my $prev_name = ''; ?

        Yes, it is entirely equivalent. See perlop for the details.

Re: perl writing to xml file (xml::writer)
by poj (Abbot) on Feb 02, 2016 at 18:00 UTC

    Build a hash of arrays (HoA) perhaps.

    #!perl use strict; use warnings; use XML::Writer; use Text::CSV; my $csv = Text::CSV->new ( { binary => 1, sep_char => ',', eol => $\, } ) or die "Cannot use CSV: ".Text::CSV->error_diag (); #input file my $input_file = 'in.csv'; open my $fh_in,'<',$input_file or die "cannot open $input_file : $!"; my %hash=(); while ( my $line = $csv->getline( $fh_in ) ){ my $name = $line->[0]; push @{$hash{$name}},$line; } close $fh_in; #output file my $output_file = "myfile.xml"; open my $fh_out,'>',$output_file or die "cannot open $output_file : $!"; my $writer = new XML::Writer( OUTPUT => $fh_out, DATA_MODE => 1, DATA_INDENT => 2 ); for my $name (sort keys %hash){ $writer->startTag("structure", "name"=>$name); for my $ar ( @{$hash{$name}} ){ $writer->startTag("value", "name" => $ar->[1], "start"=> $ar->[2], "type" => $ar->[3]); $writer->endTag("value"); } $writer->endTag("structure"); $writer->end(); } close $fh_out;
    poj
      thanks poj. I try to do it in hashes before, but not really familiar and got some error. That's why I switched back to array.