我是 perl 的新手并且一直在努力。我有一个具有以下结构的xml文件,但有数千个条目:
的test.xml
<msms_pipeline_analysis>
<spectrum_query spectrum="H_TPP08.04885.04885.2" start_scan="4885" end_scan="48887">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
<spectrum_query spectrum="L_TPP08.05765.04785.2" start_scan="4885" end_scan="48856">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
<spectrum_query spectrum="L_TPP10.87945.3485.2" start_scan="4885" end_scan="4885">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
</msms_pipeline_analysis>
我需要解析/删除“spectrum_query”节点 包含属性“spectrum”此示例中的字符串 “TPP08”即实际上它在第一个下划线和第一个点之间(后面我想要TPP09,TPP10等子集),例如。
H_的 TPP08 .04885.04885.2
并保留文件及其结构。
通过搜索,我提出了许多解决方案,这些解决方案旨在删除满足属性的节点。就我而言,此类解决方案可以删除相关节点:
#!/urs/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> new ('pretty_print' => 'indented' ) -> parsefile ( 'test.xml' );
foreach my $element ( $twig -> get_xpath('spectrum_query[@spectrum="H_TPP08.04885.04885.2"]') ) {
$element -> delete;
}
$twig -> print;
open XML, ">output.xml";
print XML $twig->toString();
close XML;
删除第一个节点。但只有特定的一个,而真正的文件有数千个条目。此外,我想保持符合标准的那些,因为反过来我必须为不包含频谱TPP08的每个其他条目运行脚本(例如TPP09,TPP10等) 。
至于确定字符串,到目前为止我已经来了这个
$string = qw(H_TPP08.05164.05164.2);
my ($substring2) = $string =~ m:.*_(.+?)?\.:;
print "$substring2\n";
哪个输出 TPP08 我想要的是什么,因为我需要用H_TPP08.XXXX或L_TPP08.XXXX保存节点
到目前为止,我还没有发现是否有办法在R中使用“!”来做负面子集。 grep,并在属性上的字符串匹配中包含grep,这样就可以解析了。对于我最有可能阅读的内容,我需要使用所有条目的属性字符串创建一个数组
my @array = map { $tag -> att('spectrum') } $twig -> get_xpath('//spectrum_query');
然后在grep之后依次评估每个条目并将其与匹配的字符串进行比较,然后只保持节点满足该条目。但是我无法用我的基本知识来解决这个问题。
任何帮助都将非常感谢!感谢
答案 0 :(得分:0)
use strict;
use warnings;
use XML::Twig;
my $xml = <<'EOF';
<msms_pipeline_analysis>
<spectrum_query spectrum="H_TPP08.04885.04885.2" start_scan="4885" end_scan="48887">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
<spectrum_query spectrum="L_TPP08.05765.04785.2" start_scan="4885" end_scan="48856">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
<spectrum_query spectrum="L_TPP10.87945.3485.2" start_scan="4885" end_scan="4885">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1">
</search_hit>
</search_result>
</spectrum_query>
</msms_pipeline_analysis>
EOF
my $twig = XML::Twig->new(pretty_print => 'indented')->parse($xml);
for my $element ($twig->get_xpath('/msms_pipeline_analysis/spectrum_query')) {
next if $element->att('spectrum') =~ /TPP08/;
$element->delete;
}
$twig->print;
输出:
<msms_pipeline_analysis>
<spectrum_query end_scan="48887" spectrum="H_TPP08.04885.04885.2" start_scan="4885">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1"></search_hit>
</search_result>
</spectrum_query>
<spectrum_query end_scan="48856" spectrum="L_TPP08.05765.04785.2" start_scan="4885">
<search_result>
<search_hit calc_neutral_pep_mass="2348.060995306391" hit_rank="1"></search_hit>
</search_result>
</spectrum_query>
</msms_pipeline_analysis>
答案 1 :(得分:0)
您可以在属性
上使用带有正则表达式的get_xpath
foreach my $element ( $twig -> get_xpath('spectrum_query[@spectrum =~ /^(?!\w_TPP08\.)/]') ) {
$element -> delete;
}
或者您可以检查每个节点的属性匹配:
foreach my $element ( $twig -> get_xpath('spectrum_query[@spectrum]') ) {
if ($element->att('spectrum')!~ m/^\w_TPP08\./) {
$element -> delete;
}
}
答案 2 :(得分:0)
执行此操作的最“琐碎”方式是在输出其余内容时浏览文件并丢弃您不想要的元素。
twig_roots
来匹配正确的spectrum_query
元素,并对它们不执行任何操作,从而有效地丢弃它们,twig_print_outside_roots
这将非常节省内存,因为内存中几乎没有任何内容。
#!/usr/bin/env perl
use strict;
use warnings;
use autodie qw(open);
use XML::Twig;
my $target = 'TPP08';
my $input = 'test.xml';
my $output = 'output.xml';
open( my $out, '>:utf8', $output);
XML::Twig->new( twig_roots => { qq{spectrum_query[\@spectrum=~/^[^_]*_$target\./]} => 1, },
twig_print_outside_roots => $out,
)
->parsefile( $input);
请注意,每个丢弃的元素都会在输出中产生一个空行,白色空间管理很棘手。如果重要,您可以使用grep -v
或使用xml_pp
删除那些。