Reputation: 120
I have an XML file which I would like to parse and use to create an arguments set for ffmpeg encoding.
This is what a dump of the xml looks like:
$VAR1 = {
'profile' => [
{
'enodingParam' => {
'videoFrameRate' => {
'arg' => '-r',
'content' => '25'
},
'audioCodec' => {
'arg' => '-acodec',
'content' => 'libfaac'
},
'videoCodec' => {
'arg' => '-vcodec',
'content' => 'libx264'
},
'videoSize' => {
'arg' => '-s',
'content' => '640x360'
},
'audioBitrate' => {
'arg' => '-ab',
'content' => '96k'
},
'videoGOP' => {
'arg' => '-g',
'content' => '90'
},
'audioRate' => {
'arg' => '-ar',
'content' => '22050'
},
'audioChannels' => {
'arg' => '-ac',
'content' => '2'
},
'videoPreset' => {
'arg' => '-vpre',
'content' => 'slow'
},
'videoBitrate' => {
'arg' => '-b',
'content' => '1200k'
}
},
'metadat' => {
'fileContainer' => '.mp4',
'profileName' => 'testpfrof1'
}
},
{
'enodingParam' => {
'videoFrameRate' => {
'arg' => '-r',
'content' => '25'
},
'audioCodec' => {
'arg' => '-acodec',
'content' => 'libfaac'
},
'videoCodec' => {
'arg' => '-vcodec',
'content' => 'libx264'
},
'videoSize' => {
'arg' => '-s',
'content' => '320x180'
},
'audioBitrate' => {
'arg' => '-ab',
'content' => '96k'
},
},
'videoGOP' => {
'arg' => '-g',
'content' => '90'
},
'audioRate' => {
'arg' => '-ar',
'content' => '22050'
},
'audioChannels' => {
'arg' => '-ac',
'content' => '2'
},
'videoPreset' => {
'arg' => '-vpre',
'content' => 'slow'
},
'videoBitrate' => {
'arg' => '-b',
'content' => '400k'
}
},
'metadat' => {
'fileContainer' => '.mp4',
'profileName' => 'testProfile2'
}
}
]
};
I would like to use a foreach loop for the encodingparam node/tagname and end up with a string which looks something like this:
-acodec libfaac -vcodec libx264 -s 640x360 -ab 96k
I am kind of stuck . This is what I have put together so far:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use XML::LibXML;
my $filename = "xml/profile.xml";
my $parser = XML::LibXML->new;
my $doc = $parser->parse_file($filename)
or die "can't parse profile file: $@";
my $root = $doc->documentElement();
my @nodeList = $doc->getElementsByTagName('enodingParam');
here is the xml file
<?xml version="1.0"?>
<profiles>
<profile>
<metadt>
<profileName>testp1</profileName>
<fileContainer>.mp4</fileContainer>
</metadt>
<enodingParam>
<videoCodec arg="-vcodec">libx264</videoCodec>
<videoPreset arg="-vpre">slow</videoPreset>
<videoBitrate arg="-b">1200k</videoBitrate>
<videoWidth arg="-w">640</videoWidth>
<videoHeight arg="-h">360</videoHeight>
<videoSize arg="-s">640x360</videoSize>
<videoFrameRate arg="-r">25</videoFrameRate>
<videoGOP arg ="-g">90</videoGOP>
<audioBitrate arg="-ab">ab 96k</audioBitrate>
<audioCodec arg="-acodec">-acodec libfaac</audioCodec>
<audioChannels arg="-ac">2</audioChannels>
<audioRate arg="-ar">"22050"</audioRate>
</enodingParam>
</profile>
<profile>
<metadt>
<profileName>testProfile22</profileName>
<fileContainer>.mp4</fileContainer>
</metadt>
<enodingParam>
<videoCodec arg="-vcodec">libx264</videoCodec>
<videoPreset arg="-vpre">slow</videoPreset>
<videoBitrate arg="-b">1200k</videoBitrate>
<videoWidth arg="-w">640</videoWidth>
<videoHeight arg="-h">360</videoHeight>
<videoSize arg="-s">640x360</videoSize>
<videoFrameRate arg="-r">25</videoFrameRate>
<videoGOP arg ="-g">90</videoGOP>
<audioBitrate arg="-ab">96k</audioBitrate>
<audioCodec arg="-acodec">libfaac</audioCodec>
<audioChannels arg="-ac">2</audioChannels>
<audioRate arg="-ar">22050</audioRate>
</enodingParam>
</profile>
</profiles>
Modified the pl script to
use warnings;
use strict;
use Data::Dumper;
use XML::LibXML;
my $filename = "xml/book.xml";
my $parser = XML::LibXML->new;
my @ffmpegargs;
my $fileName="filename";
my $doc = $parser->parse_file($filename)
or die "can't parse profile file: $@";
my $root = $doc->documentElement();
my @paramList = $doc->getElementsByTagName('enodingParam');
for my $ele (@paramList)
{
# You then need to iterate over all the children of that node...
for my $param ($ele->nonBlankChildNodes())
{
my $inparams = " " . $param->getAttribute('arg') . " " . $param->textContent ;
push ( @ffmpegargs, $inparams);
}
my $ffmpeg = join(" ", @ffmpegargs);
print "ffmpeg" . $ffmpeg, "\n";
}
It is printing out correctly. Now how do i add the following to the string $filename , profileName, containerName (from the metadat node) to the same string so that my final output looks like:
ffmpeg -vcodec libx264 -vpre slow -b 1200k -w 640 -h 360 -s 640x360 filename_profileName_containerName
ok tried zooming ue to profile. Not sure how to traverse the child nodes. Tried this. But its nor printing the right values
use warnings;
use strict;
use Data::Dumper;
use XML::LibXML;
my $filename = "xml/book.xml";
my $parser = XML::LibXML->new;
my @ffmpegargs;
my $fileName="filename";
my $doc = $parser->parse_file($filename)
or die "can't parse profile file: $@";
my $root = $doc->documentElement();
my @paramList = $doc->getElementsByTagName('profile');
for my $ele (@paramList)
{
# You then need to iterate over all the children of that node...
for my $param ($ele->findnodes('/encodingParam/*'))
{
my $inparams = " " . $param->getAttribute('arg') . " " . $param->textContent ;
push ( @ffmpegargs, $inparams);
}
my $ffmpeg = join(" ", @ffmpegargs);
print "ffmpeg" . $ffmpeg, "\n";
}
Upvotes: 0
Views: 399
Reputation: 9576
Ok, by the time you get to the end of your script, @nodeList
is a list of XML::LibXML::Element
objects.
So you start by iterating through each element of that list:
my @profiles = $doc->getElementsByTagName('profile');
for my $profile (@profiles)
{
print $profile->getElementsByTagName('profileName')->get_node(1)->textContent;
print $profile->getElementsByTagName('fileContainer')->get_node(1)->textContent;
for my $param ($profile->getElementsByTagName('enodingParam')->get_node(1)->nonBlankChildNodes())
{
print " ";
print $param->getAttribute('arg');
print " ";
print $param->textContent;
}
print "\n";
}
I'm using get_node(1)
as a shortcut instead of calling getElementsByTagName
, putting the result into an array and then working on the first element of the array.
Upvotes: 1