read an xml file in perl

trevor1940
trevor1940 used Ask the Experts™
on
Hi
I'm trying to extract elements from an XML file generated by mediainfo
I've done this before here but the format of the xml has changed

So how do I get at the file path on 'media ref' line and the other components
I'm getting "Not an ARRAY reference at"  line after dump
foreach my $file (@{$xml->{media}}) {

I tried to quote 'media ref' but didn't work

use strict;
use warnings;
use XML::Simple;
use Data::Dump qw(dump);

my $xml = XMLin('Path\\To\\Example.xml');

dump($xml);
foreach my $file (@{$xml->{media}}) {
    my ($FilePath,$NewName,$album,$movie);
    foreach my $key (qw(Complete_name CompleteName Collection Track Track_name Movie Movie_name Album Performer)) {
    print "key = $key\n";
        if (exists($file->{track}[0]{$key})){
            if(($key eq 'Complete_name') or ($key eq 'CompleteName')) {
                print 'File path = ', $file->{track}[0]{$key}, "\n";
                $FilePath = $file->{track}[0]{$key};
                }
            elsif(($key eq 'Collection') or ($key eq 'Album')){
                print 'Album = [', $file->{track}[0]{$key}, "]\n";
                $album = $file->{track}[0]{$key};
                }
            elsif($key =~ m/Track|Movie/i){
                print 'Movie = ', $file->{track}[0]{$key}, "\n";
                $movie = $file->{track}[0]{$key};
                }
            }
    }
  }  

Open in new window



Example.xml

<?xml version="1.0" encoding="UTF-8"?>
<MediaInfo
    xmlns="https://mediaarea.net/mediainfo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://mediaarea.net/mediainfo https://mediaarea.net/mediainfo/mediainfo_2_0.xsd"
    version="2.0">
<creatingLibrary version="17.10" url="https://mediaarea.net/MediaInfo">MediaInfoLib</creatingLibrary>
<media ref="Path/To/my-clip330.mov">
<track type="General">
<VideoCount>1</VideoCount>
<AudioCount>1</AudioCount>
<FileExtension>mov</FileExtension>
<Format>MPEG-4</Format>
<CodecID>M4V </CodecID>
<FileSize>763395705</FileSize>
<Duration>632.500</Duration>
<OverallBitRate_Mode>VBR</OverallBitRate_Mode>
<OverallBitRate>9655598</OverallBitRate>
<FrameRate>24.000</FrameRate>
<FrameCount>15180</FrameCount>
<StreamSize>343786</StreamSize>
<HeaderSize>168</HeaderSize>
<DataSize>8</DataSize>
<FooterSize>763395529</FooterSize>
<IsStreamable>No</IsStreamable>
<Title>A Really good title</Title>
<Movie>A Really good title</Movie>
<Album>Really good Album</Album>
<Album_Performer>Good People</Album_Performer>
<Performer>George amp: Bungle</Performer>
<Genre>GenreA GenreB</Genre>
<Recorded_Date>2017-08-16</Recorded_Date>
<Rating>None</Rating>
<extra>
<Title_Sort>Really good Title - 02</Title_Sort>
</extra>
</track>

<track type="Video">
<!--Removed as not needed -->
</track>

<track type="Audio">
<!--Removed as not needed -->
</track>

</media>
</MediaInfo>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Prepress/OMS Specialist
Commented:
Since your data structure has changed, you must force the data structures into arrays, even if there is only one.  You do that by passing the option ForceArray => 1 when reading your XML file (see line 6 below).

See this code:
use strict;
use warnings;
use XML::Simple;
use Data::Dump qw(dump);

my $xml = XMLin('tmp.xml', ForceArray => 1);

#dump($xml);
foreach my $file (@{$xml->{media}}) {
  dump($file);
  print "File path = ", $file->{ref}, "\n";
  my ($FilePath,$NewName,$album,$movie);
  foreach my $key (qw(Complete_name CompleteName Collection Track Track_name Movie Movie_name Album Performer)) {
    print "key = $key\n";
    if (exists($file->{track}[0]{$key})) {
      if(($key eq 'Complete_name') or ($key eq 'CompleteName')) {
        print 'File path = ', $file->{track}[0]{$key}, "\n";
        $FilePath = $file->{track}[0]{$key};
      } elsif (($key eq 'Collection') or ($key eq 'Album')) {
        print 'Album = [', $file->{track}[0]{$key}, "]\n";
        $album = $file->{track}[0]{$key};
      } elsif($key =~ m/Track|Movie/i) {
        print 'Movie = ', $file->{track}[0]{$key}, "\n";
        $movie = $file->{track}[0]{$key};
      }
    }
  }
}

Open in new window

Note that I have added code on lines 10 and 11 to dump the data structure of the individual media node (see below) and display the file path.

{
  ref => "Path/To/my-clip330.mov",
  track => [
    {
      Album               => ["Really good Album"],
      Album_Performer     => ["Good People"],
      AudioCount          => [1],
      CodecID             => ["M4V "],
      DataSize            => [8],
      Duration            => ["632.500"],
      extra               => [{ Title_Sort => ["Really good Title - 02"] }],
      FileExtension       => ["mov"],
      FileSize            => [763395705],
      FooterSize          => [763395529],
      Format              => ["MPEG-4"],
      FrameCount          => [15180],
      FrameRate           => ["24.000"],
      Genre               => ["GenreA GenreB"],
      HeaderSize          => [168],
      IsStreamable        => ["No"],
      Movie               => ["A Really good title"],
      OverallBitRate      => [9655598],
      OverallBitRate_Mode => ["VBR"],
      Performer           => ["George amp: Bungle"],
      Rating              => ["None"],
      Recorded_Date       => ["2017-08-16"],
      StreamSize          => [343786],
      Title               => ["A Really good title"],
      type                => "General",
      VideoCount          => [1],
    },
    { type => "Video" },
    { type => "Audio" },
  ],
}

Open in new window

Author

Commented:
Thanx Jim that got it working

I was getting this from the dump

key = Movie
Movie = ARRAY(0x319e7f0)

so changed to

[code]
elsif($key =~ m/Track|Movie/i) {
        print 'Movie = ', $file->{track}[0]{$key}[0], "\n";
        $movie = $file->{track}[0]{$key}[0];
      }
[/code]

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial