按行解析一个XML文件

问题描述:

所以问题在这里。我正试图解析来自GenBank的XML文件信息。该文件包含多个DNA序列的信息。我已经完成了genbacnk(TINY xml和INSD xml)中的其他两种xml格式,但纯xml让我很头疼。这是我的程序应该如何工作。下载一个xml格式的文件,其中包含来自GenBank的X个序列信息。运行我的perl脚本,它可以逐行搜索该xml文件,并以fasta格式将我想要的信息打印到新文件中。这是:>序列名称和信息\ n序列\ n>序列名称......并且直到您拥有来自xml文件的所有序列。我的问题是,在纯xml中,序列本身出现在序列基因或基因座的标识符之前。序列的基因或基因座应与“>”一致。下面是我从打开该文件,并通过它分析的点有代码:按行解析一个XML文件

open(New_File, "+>$PWD_file/$new_file") or die "\n\nCouldn't create file. Check permissions on location.\n\n"; 

    while (my $lines = <INSD>) { 
     foreach ($lines) { 
      if (m/<INSDSeq_locus>.*<\/INSDSeq_locus>/) { 
       $lines =~ s/<INSDSeq_locus>//g and $lines =~ s/<\/INSDSeq_locus>//g and $lines =~ s/[a-z, |]//g; #this last bit may cause a bug of removing the letters in the genbank accession number 
       $lines =~ s/ //g; 
       chomp($lines); 
       print New_File ">$lines\_"; 
      } elsif (m/<INSDSeq_organism>.*<\/INSDSeq_organism>/) { 
       $lines =~ s/<INSDSeq_organism>//g and $lines =~ s/<\/INSDSeq_organism>//g; 
       $lines =~ s/(\.|\?|\-|)/_/g; 
       $lines =~ s/_{2,}/_/g; 
       $lines =~ s/_{1,}$//; 
       $lines =~ s/^>*_{1,}//; 
       $lines =~ s/\s{2}//g; 
       chomp($lines); 
       print New_File "$lines\n"; 
      } elsif (m/<INSDSeq_sequence>.*<\/INSDSeq_sequence>/) { 
       $lines =~ s/<INSDSeq_sequence>//g and $lines =~ s/<\/INSDSeq_sequence>//g; 
       $lines =~ s/ //g; 
       chomp($lines); 
       print New_File "$lines\n"; 
      } 
     } 
    } 
    close INSD; 
    close New_File; 
} 

有两个地方找到基因/基因信息。该信息位于这两个标记之间:LOCUS_NAME或GENE_NAME。会有一个,或另一个。如果有人有信息,其他人将是空的。无论哪种情况,都需要添加到> .......行的末尾。

感谢,

AlphaA

PS - 我试图打印信息,以“文件”做开放“$ NA”,“>”序列到,然后与移动上程序,找到基因信息,将其打印到>行,然后读取$ NA文件并将其打印到行后面的行中。我希望这很清楚。

+12

是否有你选择不使用XML解析库的原因? –

+0

也许输入,电流输出和实际输出的例子会很好。 – DavidEG

+0

@DavidEG:那么,OP指定了GenBank,所以http://www.ncbi.nlm.nih.gov/genbank/和ftp://ftp.ncbi.nih.gov/genbank/ – derobert

在我看来,您应该使用XSLTXPath导航到您需要的数据。

正如@布莱恩建议,使用已建立的XML解析技术和库更容易。

甚至有一个Perl library for XSLT

使用XML解析器。我不是生物学家,我不确定你想要的最终格式,但它应该很简单,以此为出发点。 $_[1]在匿名子文件中包含一个哈希引用,从上面我可以告诉的,我认为你想要解析所需标记的父标记时保存的所有内容。它应该很容易打印出的$元素_ [1],你希望它是格式:

use strict; 
use warnings; 

use XML::Rules; 
use Data::Dumper; 

my @rules = (
    _default => '', 
    'INSDSeq_locus,INSDSeq_organism,INSDSeq_sequence' => 'content', 
    INSDSeq => sub { delete $_[1]{_content}; print Dumper $_[1]; return }, 
); 

my $p = XML::Rules->new(rules => \@rules); 
$p->parsefile('sequence.gbc.xml'); 

而这仅仅是使打印你想要的标签很容易。或者,如果你想一些其他的标签,我真的会做的就是这个(你并不真正需要的@tags变量在所有如果你只是用元素打印元件):

my @tags = qw(
    INSDSeq_locus 
    INSDSeq_organism 
    INSDSeq_sequence 
); 

my @rules = (
    _default => 'content', 
    # Elements are, e.g. $_[1]{INSDSeq_locus} 
    INSDSeq => sub { print "$_: $_[1]{$_}\n" for @tags; return; }, 
); 

有:

my $p = XML::Rules->new(rules => \@rules, stripspaces => 4); 
+0

不需要'@ tags'数组和地图。您可以指定一个字符串几个标签名称字面,并用逗号分隔它们: 我@rules =( “INSDSeq_locus,INSDSeq_organism,INSDSeq_sequence” =>“内容”, ... – Jenda

+0

@Jenda - 注意(和我应该是已知的)并更新。 – runrig