从XML获取图像

时间:2013-06-23 13:13:49

标签: xml perl xml-parsing mod-perl

我想从下面的XML文件中获取图片。

如何从下面的XML文件中获取图片网址的一部分,但我无法收到它:

my @imageurl;     
foreach my $img(@{$_->{images}}){     
my $imgurl = &makeScalar($img->{image}->[0]); 

我觉得这里出了点问题:my $imgurl = &makeScalar($img->{image}->[0]); 因为如果这样做:

my @imageurl;     
foreach my $img(@{$_->{images}}){     
my $imgurl = &makeScalar($img->{image_0}->[0]); 

我只获得一张图片而不是3张图片?

图像所在的XML文件:

<images>
    <image_0>url of image 1</image_0>
    <image_1>ulr of image 2</image_1>
    <image_2>url of image 3</image_2>
 </images>

完整代码:

package test::test1_123;
use strict;
use warnings;
use onb;
use base qw/;
use URI::URL;
use XML::Simple;
use Data::Dumper;
#use Unicode::String qw(utf8 latin1 utf16be);
use constant TASK_ID => 2084;
use constant CR_TYPE => '2084';
use constant IMAGE_PATH => "/home/public_html/files/";#"images/";

sub new
{
    #Initialization
    my $class = shift;
    my $self = $class->SUPER::new(CR_TYPE, TASK_ID);
    bless $self, $class;
    #Initialization ends

    my $url = 'http://www.url.com.asp?id=18&show=1000&page=1';


    my $xml = $self->geturl('url'=>$url);
    $self->extract($xml);


        #$self->teardown;
}

sub extract{
my $self = shift;
my $xmlfile = shift;
my $xml = new XML::Simple(ForceArray=>1,'KeyAttr' =>'image');
my $data = $xml->XMLin($xmlfile);


PASS:foreach(@{$data->{property}}){    

      my $property = &makeScalar($_->{id}->[0]);    

# get images from XML
      my @imageurl;   
      foreach my $img(@{$_->{images}}){
    my $imgurl = &makeScalar($img->{image_0}->[0]);

      push @imageurl,$imgurl;
      }
}
        my $detail = {};

          $detail->{cr_type}  = CR_TYPE;
          $detail->{catid}    = '434';
          $detail->{userid}   = '2084'; 
          $detail->{hw_added}   = &get_date;
          $detail->{hw_updated} = &get_date;

            unless ($self->exists_item($detail->{site_id}))
        {
            my $insertid = $self->add(%{$detail});

     #get last insert id and update images

     #get images and save them into a folder
            my $count = 0;
            my $imgstr;
            foreach my $u(@imageurl){
               my $res = $self->geturl('url'=>$u);
               my $filename = IMAGE_PATH . "item_" . $insertid;
                  $filename = $filename . '_' . $count if $count > 0;
                  $filename = $filename . ".jpg";
                              $imgstr = $imgstr . "" . "item_" . $insertid .".jpg" if $count == 0;
                  $imgstr = $imgstr . "\n" . "item_" . $insertid . "_" . $count .".jpg" if $count > 0;
                  $count++;
                  open FILE,">$filename";binmode(FILE);print FILE $res;close FILE;
                  &ResizeImg($filename,100,100) if -e $filename;

            }

            my $imgs ={};
               $imgs->{link_id} = $insertid;
               $imgs->{images}  = $imgstr;
            $self->update_img(%{$imgs});

        }
}
}



sub get_date {
    my ($sec, $min, $hour, $day, $mon, $year, $dweek, $dyear, $daylight) = localtime(time());
    my (@months) = qw!Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec!;
    ($day < 10) and ($day = "0$day");
    $year = $year + 1900;
    $mon = $mon +1;
     return "$year-$mon-$day $hour-$min-$sec";

}
sub makeScalar() {
    if ($_[0]=~/HASH\(0x(\d|\w)+\)/) { return ''; }
    return $_[0];
}
sub ResizeImg
{
   my ($file,$width_max,$height_max) = @_;
   eval { require GD; };
   return if $@;
   my $image = GD::Image->new($file);
   return unless $image;
   my ($width,$height) = $image->getBounds();
   my ($dx,$dy)=(0,0);
   if($width/$height >= $width_max/$height_max) ### Horizontal
   {
      $dx = sprintf("%.0f", ($width-$width_max*$height/$height_max)/2 );
   }
   else
   {
      $dy = sprintf("%.0f", ($height-$height_max*$width/$width_max)/2 );
   }
   my $thumb = GD::Image->newTrueColor($width_max,$height_max);
   $thumb->copyResampled($image,0,0,$dx,$dy,$width_max,$height_max,$width-2*$dx,$height-2*$dy);

   my $jpegdata = $thumb->jpeg(70);
   $file=~s/\.(jpg|jpeg|gif|png|bmp)$//i;
   $file=~s/\/files\//\/files\/small\//i;
   open(FILE,">$file.jpg")||warn "can't write th:$!";
   binmode FILE;
   print FILE $jpegdata;
   close(FILE);
}

1;

1 个答案:

答案 0 :(得分:3)

首先, XML :: Simple是一个不推荐使用的模块,如果可能的话,你应该避免,正是因为你在这里看到的原因:通常很难预测和处理Perl它产生的数据结构。模块文档本身说明了这个

  

不鼓励在新代码中使用此模块。其他模块是       可用,提供更直接和一致的界面。       特别强烈建议使用XML :: LibXML。

     

这个模块的主要问题是大量的选择和       这些选项互动的任意方式 - 经常与之相互作用       意想不到的结果。

因此,如果可能,我建议您迁移到XML::LibXMLXML::Twig

目前我看不出你的代码无法正常工作的原因,如果你不显示你的XML,那么没有人可以提供帮助。在我看来,使用XML::Simple选项,@{$data->{property}}的每个元素都应如下所示。

{
  id => [99],
  images => [
    {
      image_0 => ["url of image 1"],
      image_1 => ["url of image 2"],
      image_2 => ["url of image 3"],
    },
  ],
}

所以for my $img (@{$_->{images}}) { ... }循环遍历看起来像

的单元素数组
[
  {
    image_0 => ["url of image 1"],
    image_1 => ["url of image 2"],
    image_2 => ["url of image 3"],
  },
]

$img->{image_0}[0]应为字符串url of image 1

显示您的数据和真正的计划,我们将能够为您提供进一步的帮助。