使用perl和libXML解析xml

时间:2014-05-01 04:27:41

标签: xml perl parsing ffmpeg libxml2

我有一个XML文件,我想解析并用它来为ffmpeg编码创建一个参数集。

这就是xml的转储:

$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'
                                   }
                       }
                     ]
        };

我想为encodingparam节点/标记名使用foreach循环,最后得到一个如下所示的字符串:

-acodec libfaac -vcodec libx264 -s 640x360 -ab 96k 

我有点卡住了。这就是我到目前为止所做的:

#!/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');

这是xml文件

<?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>

将pl脚本修改为

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";
}

正确打印出来。现在我如何将以下内容添加到字符串中 $ filename,profileName,containerName(来自metadat节点)到相同的字符串,以便我的最终输出如下所示:

ffmpeg -vcodec libx264  -vpre slow  -b 1200k  -w 640  -h 360  -s 640x360 filename_profileName_containerName 

确定尝试缩放你的个人资料。不确定如何遍历子节点。试过这个。但它也不打印正确的值

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";
}

1 个答案:

答案 0 :(得分:1)

好的,当你到达脚本结束时,@nodeListXML::LibXML::Element个对象的列表。

因此,您首先遍历该列表的每个元素:

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";
}

我使用get_node(1)作为快捷方式,而不是调用getElementsByTagName,将结果放入数组中,然后处理数组的第一个元素。