parsing xml with perl

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Ian Hoff
    New Member
    • Dec 2010
    • 1

    #1

    parsing xml with perl

    This should be simple enough (famous last words)...
    I have an SVG file I need to split the elements from into separate svg files. this is still a work in progress but I am stuck.
    they need the header info and then the data block.
    each element written to a separate indexed file name (still working out how to get the indexed range from aaaa-zzzz so even windows will keep the in order).
    when I run the code I get "error with <?xml version="1.0" encoding="UTF-8" standalone="no" ?>: file invalid argument"
    I'm know its reading and interpolating the special characters... I'm sure my code is sloppy its the first thing I've written in 5 years. I'm also sure it could be handled in a far less klunky way than I went about it.
    Anything from telling me how to get past that single step to the 12 or so lines of code that would get this done the right way is appreciated.


    Code:
    #!/usr/local/bin/perl
    #use strict;
    use warnings;
    
    my $infile = <>;
    my $count = 0;
    my $outfile = ">>Form_" . $count . '.svg';
    my @arr;
    
    sub write_slice {
    open(OUT,">$outfile") or die "Error with outfile: $!\n";  
    print OUT @arr;
    close(OUT);
    @arr=();
    $count++;
    $outfile = ">>Form_" . $count . '.svg';
    create_slice();
    }
    
    sub create_slices {
    foreach my $line (@arr) {
    
      if ($line !~ '</g>') {
      push @arr, "$line\n";
      next;
      }
      elsif ($line =~ '</g>') {
      push @arr, "$line\n";
      next;
      }
      else {
      push @arr, "$line\n";
      write_slice();
      }
    }
    }
    
    sub create_head {
    open(OUT,">headinfo") or die "Error with outfile: $!\n";  
    print OUT @arr;
    close(OUT);
    @arr=();
    $outfile = ">>Form_" . $count . '.svg';
    create_slices();
    }
    
    chomp $infile;
    open IN, $infile or die "Error with infile $infile: $!\n";
    my @data=<IN>;
    close(IN);
    
     foreach my $line (@data) {
    
      if ($line !~ "</metadata>") {
      push @arr, "$line\n";
      next;
      }
      elsif ($line =~ "</metadata>") {
      push @arr, "$line\n";
      next;
      }
      else {
      push @arr, "$line\n";
      create_head();
      }
     }
    example file truncated for size;
    [sample]
    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <!-- Created with vcg library -->
    ... (bunch of stuff)
    </rdf:RDF>
    </metadata>

    <rect width= " 23.983494cm " height= " 23.983480cm " x="1.000000cm " y="1.000000cm " style= " stroke-width:1pt; fill-opacity:0.0; stroke:rgb(0,0, 0)" />
    ... (more stuff)
    </g>

    <rect width= " 23.983494cm " height= " 23.983480cm " x="1.000000cm " y="1.000000cm " style= " stroke-width:1pt; fill-opacity:0.0; stroke:rgb(0,0, 0)" />
    ... (more stuff)
    </g>
    etc..
    </svg>
    </g>
    </svg>
    [/sample]
  • RonB
    Recognized Expert Contributor
    • Jun 2009
    • 589

    #2
    Don't try to manually parse xml with a simplistic rexeg and simplistic if/elsif/else block.

    Use one of the standard XML parsers on cpan.


    Here are 2 of the more commonly used parsers.

    Comment

    Working...