Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Perl编辑XML文件?_Xml_Perl - Fatal编程技术网

如何使用Perl编辑XML文件?

如何使用Perl编辑XML文件?,xml,perl,Xml,Perl,我有一个电影收藏目录,带有文件夹和文件的本地链接,便于访问。最近,我重新整理了我的整个硬盘空间,我需要更新链接,我正试图用Perl自动完成这项工作 我可以将数据导出到XML文件中,然后再次导入。我可以使用提取新的文件路径,但我遇到了两个问题。我不知道如何将新文件路径中的$title与XML文件中相应的$title连接起来。我第一次处理这样的文件,我不知道如何进行替换过程。这就是我到现在为止所做的 use strict; use warnings; use File::Basename; us

我有一个电影收藏目录,带有文件夹和文件的本地链接,便于访问。最近,我重新整理了我的整个硬盘空间,我需要更新链接,我正试图用Perl自动完成这项工作

我可以将数据导出到XML文件中,然后再次导入。我可以使用提取新的文件路径,但我遇到了两个问题。我不知道如何将新文件路径中的
$title
与XML文件中相应的
$title
连接起来。我第一次处理这样的文件,我不知道如何进行替换过程。这就是我到现在为止所做的

use strict; 
use warnings; 
use File::Basename;
use File::Find; 
use File::Spec;
use XML::Simple;
use Data::Dumper;



my $dir_target = 'D:/Movies/';
my %titles_locations = ();

find(\&file_handler, $dir_target);
sub file_handler {
   /\.iso$/ or return;       

   my $fn = $File::Find::name;
   $fn =~ s/\//\\/g;
   $fn =~ /(.*\\)(.*)/;
   my $path = $1;
   my $filename = $2;

   my $title = (File::Spec->splitdir($fn))[2];
   $title =~ s/(.*?)\s\(\d+\)$/$1/;
   $title =~ s/~/:/;
   $title =~ s/`/?/;

   my $link_local = '<link><description>Folder</description><url>'.$path.'</url><urltype>Movie</urltype></link><link><description>'.$filename.'</description><url>'.$fn.'</url><urltype>Movie</urltype></link>' unless $title eq '';

   $titles_locations{$title} = {'filename'=>$filename, 'path'=>$path };
}

   my $xml_in = XMLin('somepath/test.xml', ForceArray => 1, KeepRoot => 1);

   my $title = {'key1' => 'title', 'key2' => 'links'};

   foreach my $link (keys %$title) {
   }

   print Data::Dumper->Dump([$title]);

   my $xml_out = XMLout($xml_in, OutputFile => 'somepath/test_out.xml', KeepRoot=>1);       
使用严格;
使用警告;
使用File::Basename;
使用File::Find;
使用File::Spec;
使用XML::Simple;
使用数据::转储程序;
我的$dir_目标='D:/Movies/';
我的%titles_位置=();
查找(\&file\u处理程序,$dir\u目标);
子文件处理程序{
/\.iso$/或退货;
我的$fn=$File::Find::name;
$fn=~s/\/\\\/g;
$fn=~/(.\\)(.*)/;
我的$path=$1;
我的$filename=$2;
我的$title=(File::Spec->splitdir($fn))[2];
$title=~s/(.*)\s\(\d+\)$/$1/;
$title=~s/~/:/;
$title=~s/`/;
my$link_local='Folder'.$path.'Movie'.$filename'.$fn.'Movie'除非$title eq'';
$titles\u位置{$title}={'filename'=>$filename,'path'=>$path};
}
my$xml_in=XMLin('somepath/test.xml',ForceArray=>1,KeepRoot=>1);
我的$title={'key1'=>'title','key2'=>'links'};
foreach my$链接(键%$标题){
}
打印数据::转储程序->转储([$title]);
我的$xml\u out=XMLout($xml\u-in,OutputFile=>somepath/test\u-out.xml',KeepRoot=>1);
这是我需要编辑的数据片段。 如果发现imdb和DVD链接-请勿触摸。 如果找到本地链接,请替换,否则请插入。 我愿意自己完成代码,但需要一些指导如何进一步进行。 谢谢

$title
.......
IMDB
http://www.imdb.com/title/VARIABLE 
统一资源定位地址
DVD帝国
http://www.dvdempire.com/VARIABLE 
统一资源定位地址
文件夹
老路
电影
旧文件名
旧文件名路径
电影

我将提供一个合理的方法-如果您希望它更加充实,请发表评论

  • 声明哈希
    my%titles_locations=()在开头

  • 您应该将XML处理移出
    sub a
    (请称之为可读的,比如
    sub file\u handler
    :)

    文件处理程序应该做的是:

    • 像现在一样构建
      $title
      $link\u local

    • 将它们存储在
      %titles\u位置
      散列中,其中
      $title
      是键,hashref包含的值为
      {'filename'=>$filename',path'=>$path}

  • 现在,在您的代码中,在调用
    find()
    之后,您将调用XMLin
    $xml_in
    应成为一个hashref数组(或将“root”键映射到一个hashref数组的hashref)。数组中的每个hashref将代表一个标题

  • 在那之后,你将在标题的数组引用上循环

    arrayref的每个元素(称之为
    $title
    )将是一个具有两个键的hashref,
    “title”
    “links”

    “title”
    键的值中,从
    %titles\u位置
    哈希中查找新路径和文件名

    “links”
    键的值将是一个hashref映射“link”到一个hashref数组。我不想在这里详细说明数据结构,但通过打印
    data::Dumper->Dump([$title]);

    然后,您将在这些链接hashref上循环。对于每个链接(称为
    $link
    ):

    • 如果
      $link->{urltype}
      ne“Movie”,请不要管它(
      next;
    • 如果
      $link->{description}
      eq“文件夹”,则将
      $link->{url}
      值替换为从
      %titles\u位置
      哈希中找到的新路径
    • 否则,它是一个文件,用从
      %titles\u locations
      散列中找到的新文件路径替换
      $link->{url}
    如果
    $title
    不在
    %titles\u位置
    哈希中,可能会添加一些错误处理

  • 完成所有循环后,只需将
    $xml\u放入
    (现在包含更新的信息)并传递到
    XMLout()

  • 完成

    摆脱并使用仅用于此类任务的操作。遍历和元素操作内置于Twig中。Twig完成大部分工作时,需要考虑的问题要少得多

    就将旧路径连接到新路径而言,您所拥有的数据没有太多可操作性。如果它们是相同的文件名,但位于不同的文件夹中,则如果它们是唯一的文件名,则这可能是您匹配新路径和旧路径的方式。以下是所有内容,除了让所有新路径填充
    %new\u paths

    #!perl
    
    use File::Basename qw(basename);
    use XML::Twig;
    
    my %new_paths = (
             # filename => new_path
             ...
             ); 
    
    my $twig = XML::Twig->new(
        twig_handlers => 
          {
          link   => \&rewrite_link,
          },
        pretty_print => 'indented',
        );
    
    $twig->parse( *DATA );
    $twig->flush;
    
    sub rewrite_link
        {
        my( $link ) = $_;
    
        return unless $link->field( 'urltype' ) eq 'Movie';
    
        # this is from the old file
        my $basename = basename( $link->field( 'url' ) );
    
        unless( exists $new_paths{ $basename } )
            {
            warn "Didn't find a new location for $basename!\n";
            return;
            }
    
        $link->first_child( 'url' )->set_text( $new_paths{ $basename } );
        }
    
    __END__
    <titles>
    <entry>
        <title>$title</title>
        <links>
            <link>
                <description>IMDB</description> 
                <url>http://www.imdb.com/title/VARIABLE</url> 
                <urltype>URL</urltype> 
            </link>
            <link>
                <description>DVD Empire</description> 
                <url>http://www.dvdempire.com/VARIABLE</url> 
                <urltype>URL</urltype> 
            </link>
            <link>
                <description>Folder</description>
                <url>OLD_FOLDERPATH</url>
                <urltype>Movie</urltype>
            </link>
            <link>
                <description>OLD_FILENAME</description>
                <url>OLD_FILENAMEPATH</url>
                <urltype>Movie</urltype>
            </link>
        </links>
    </entry>
    </titles>
    
    #!perl
    使用文件::Basename qw(Basename);
    使用XML::Twig;
    我的%new_路径=(
    #filename=>新路径
    ...
    ); 
    my$twig=XML::twig->new(
    细枝处理程序=>
    {
    link=>\&重写链接,
    },
    漂亮的打印=>“缩进”,
    );
    $twig->parse(*数据);
    $twig->flush;
    子重写链接
    {
    我的($link)=$\;
    返回,除非$link->field('urltype')eq'Movie';
    #这是旧档案中的
    我的$basename=basename($link->field('url'));
    除非(存在$new_路径{$basename})
    {
    警告“未找到$basename的新位置!\n”;
    返回;
    }
    $link->first_child('url')->set_text($new_path{$basename});
    }
    __结束__
    $title
    IMDB
    http://www.imdb.com/title/VARIABLE 
    统一资源定位地址
    DVD帝国
    http://www.dvdempire.com/VARIABLE 
    统一资源定位地址
    文件夹
    老路
    电影
    
    #!perl
    
    use File::Basename qw(basename);
    use XML::Twig;
    
    my %new_paths = (
             # filename => new_path
             ...
             ); 
    
    my $twig = XML::Twig->new(
        twig_handlers => 
          {
          link   => \&rewrite_link,
          },
        pretty_print => 'indented',
        );
    
    $twig->parse( *DATA );
    $twig->flush;
    
    sub rewrite_link
        {
        my( $link ) = $_;
    
        return unless $link->field( 'urltype' ) eq 'Movie';
    
        # this is from the old file
        my $basename = basename( $link->field( 'url' ) );
    
        unless( exists $new_paths{ $basename } )
            {
            warn "Didn't find a new location for $basename!\n";
            return;
            }
    
        $link->first_child( 'url' )->set_text( $new_paths{ $basename } );
        }
    
    __END__
    <titles>
    <entry>
        <title>$title</title>
        <links>
            <link>
                <description>IMDB</description> 
                <url>http://www.imdb.com/title/VARIABLE</url> 
                <urltype>URL</urltype> 
            </link>
            <link>
                <description>DVD Empire</description> 
                <url>http://www.dvdempire.com/VARIABLE</url> 
                <urltype>URL</urltype> 
            </link>
            <link>
                <description>Folder</description>
                <url>OLD_FOLDERPATH</url>
                <urltype>Movie</urltype>
            </link>
            <link>
                <description>OLD_FILENAME</description>
                <url>OLD_FILENAMEPATH</url>
                <urltype>Movie</urltype>
            </link>
        </links>
    </entry>
    </titles>