用于创建目录文件列表的XML的脚本

时间:2011-01-29 09:23:35

标签: xml perl

有人可以通过文件类型建议一个脚本来创建所有文件的xml表示,以及子目录(在Windows上)的xml表示。例如,如果当前目录名称是mypics,那么对于所有jpg的

<?xml version="1.0" encoding="utf-8"?>
<images xmlns="http://mydomain.com/images" version="1.0">
  <image>
      <big_url>myassets/pics/funnypics/big_pics/down.jpg</big_url>
  </image>
  <image>      
      <big_url>assets/pics/funnypics/big_pics/spider.jpg</big_url>
  </image>  
</images>

然后是pdf的

<?xml version="1.0" encoding="utf-8"?>
<pdfs xmlns="http://mydomain.com/pdf" version="1.0">
  <pdf>
      <big_url>myassets/pics/funnypics/big_pics/down.pdf</big_url>
  </pdf>
  <pdf>      
      <big_url>assets/pics/funnypics/big_pics/spider.pdf</big_url>
  </pdf>  
</pdfs>

因为,filetype的数量是无限的,我可以扩展建议的脚本

3 个答案:

答案 0 :(得分:2)

这应该让你开始:

#!/usr/bin/perl
use warnings;
use strict;
use File::Find;
use XML::Simple;

my $dir = shift || '.';

my %files;
find \&by_extension, $dir;
print XMLout \%files;

sub by_extension {
    return if /^\./;                    # skip dotfiles
    return unless -f;                   # skip non-files
    return unless /\.([^.]+)$/;         # skip if no filename extension
    my $ext = lc $1;                    # ignore case
    $File::Find::name =~ s#^\Q$dir/##;  # trim starting directory name
    push @{$files{$ext . '_files'}{$ext}}, $File::Find::name;
}

答案 1 :(得分:1)

在不知道Perl及其读取目录或处理XML的方法这是一些伪代码,您可以将其用作模板:

strFileExtensionToMap="jpg"
strNodeName="image"
strCollectionName="images"
currentXMLNode=XML.CreateElement(strCollectionName)
StartFolder=Filesystem.GetFolder([however to get folder])
Call RecursiveMapContents(StartFolder)


RecursiveMapContents(folder){
    For each file in folder.Files
    {
        if (file.extension=strFileExtensionToMap)
        xmlFile=XML.CreateElement(strNodeName)
        big_Url=XML.CreateElement("big_url)
        big_url.text=file.path
        xmlFile.AppendChild(big_url)
        currentXMLNode.AppendChild(xmlFile)
    }

    For each subFolder in folder.Folders
    {

        call RecursiveMapContents(subFolder)
    }
}

当然,您可以使用文件类型作为文件元素的属性来使XML更通用:

<file type="image"/>

您还可以使用

映射实际的嵌套目录结构
<folder name="foldername" path="folderpath"> instead of <images>

然后你可以在调用RecursiveMapContents时包含当前的folderNode,以便文件和子文件夹嵌套在其中,为您提供:

<folder name="foldername" path="folderpath">
    <file type="image">
        <big_url>file path</big_url>
    </file>
    <file type="image">
        <big_url>file path</big_url>
    </file>
    <folder name="foldername" path="folderpath">
        <file type="image">
            <big_url>file path</big_url>
        </file>
        <file type="image">
            <big_url>file path</big_url>
        </file>
    </folder>
</folder>

我没有包含名称空间,但我承认对于为什么你想要图像和pdf的单独名称空间有点神秘。命名空间的要点是为一组元素提供唯一的命名(因此,如果您想使用其XML,则其他人的图像元素不会与您的图像元素混淆)。如果你真的需要一个名称空间,那么“http://mydomain.com”应该足够你所有的元素名称。命名空间说“这个元素,我们使用速记图像实际上称为thisnamespace:image”。因此,除非你有两种类型的图像元素(一种在pdfs中,另一种在图像中)并且它们不相同,单个名称空间就足够了。

还可以做更多的事情来使您的XML更通用,并且可能更简洁。这主要取决于设计XML格式的人是否指定文件路径之类的东西应该是文件元素的属性还是子元素(如big_url),这取决于数据是否需要限定(例如filepath =“this filepath“type =”filesystem | http“应该使用子元素。”

很抱歉,这不是Perl的答案,但我希望它有所帮助。

答案 2 :(得分:1)

以下perl代码可以解决问题(可能减去XML文件缩进):

package FilesToXml;
use IO;
use File::Find;
use XML::Writer;

use vars qw(@ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(SetRequestedType GenerateXml);

my $group_name = "";
my $file_type = "";
my $ext = "";
my $writer = "";

sub SetRequestedType
{
    $group_name = shift;
    $file_type = shift;
    $ext = shift;
}

sub wanted
{
    if ($File::Find::name =~ /\.$ext$/)
    {
        $writer->startTag($file_type);
        $writer->startTag('big_url');
        $writer->characters($File::Find::name);
        $writer->endTag();
        $writer->endTag();
    }    
}

sub GenerateXml
{
    my $filename = shift;
    my $directory = shift;

    my $output = new IO::File(">$filename");
    $writer = new XML::Writer( OUTPUT => $output );

    $writer->xmlDecl( 'UTF-8' );
    $writer->startTag( $group_name, 'xmlns' => 'http://mydomain.com/'.$group_name, 
                        'version' => '1.0' );
    find(\&wanted, $directory);
    $writer->endTag();  
}

package main;

FilesToXml::SetRequestedType('docs', 'doc', 'docx');
FilesToXml::GenerateXml("output.xml", ".");

您基本上需要使用文件组的类型,描述单个文件的字符串和文件扩展名来调用SetRequestedType。然后,您只需要使用XML输出文件名和要搜索的目录调用GenerateXml

它在Windows上使用ActivePerl。可能需要在其他环境中进行一些小的调整。