从Perl中的正则表达式获取Xml标记值

时间:2016-09-13 07:51:21

标签: regex perl

我有xml,其中我有标签<test>Value</test>。我想得到标签的值。我想用Perl正则表达式来做 下面是我的xml示例:

<?xml version="1.0"?>
<t_volume>
<test>Value</test>
<info>
<info_name>FZGA34177.b1</info_name>
<center_project>4085729</center_project>
<base_file>SETARIA_ITALICA/JGI/fasta/FZGA34177.b1.fasta</base_file>
</info>
</t_volume>

我想获得此标记<test>Value</test>的值。我尝试过,但我无法获得该值。

$data = ($xml =~/<test>(.*?)<\/test>/i);

在xml中我得到的xml也像

<Test RequestId="1" RequestorId="test" ResponderId="Test">

我怎样才能获得RequestorId

的值

3 个答案:

答案 0 :(得分:2)

不要使用正则表达式来解析XML。使用适当的XML处理工具,即XML::LibXML

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use XML::LibXML;

my $dom = 'XML::LibXML'->load_xml( location => shift );

my $data = $dom->findvalue('t_volume/test');
say $data;

my $requestor_id = $dom->findvalue('//Test/@RequestorId');
say $requestor_id;

答案 1 :(得分:2)

正则表达式是用于XML的bad idea,因为正则表达式不是上下文,而XML就是上下文。问题是 - 有一堆语义上相同的XML部分可以合法地变化并且会绊倒regex。您可以通过这样做来创建脆弱的代码,因为它可能因为上游(合法的,规范内)更改而有一天会中断。

E.g:

<root>
<Test RequestId="1" RequestorId="test" ResponderId="Test">
</Test>
</root>

或者:

<root>
  <Test RequestId="1" RequestorId="test" ResponderId="Test"></Test>
</root>

或者:

<root>
  <Test
      RequestId="1"
      RequestorId="test"
      ResponderId="Test"></Test>
</root>

或者:

<root
><Test
RequestId="1"
RequestorId="test"
ResponderId="Test"
></Test></root>

或者:

<root>
  <Test RequestId="1" RequestorId="test" ResponderId="Test"/>
</root>

这些都在语义上是相同的,但我很确定你会被regex用来安全地处理上述所有内容(以及你可能遇到的任何其他内容)< / p>

另外:

  • 文档树中其他位置的类似匹配。 (可以是许多Test元素)
  • 更改属性排序/在线状态。 (所以匹配不再工作)。
  • 具有子元素的<Test>元素,因为您是通配符,它​​会捕获那些元素,而不是属性。

幸运的是,您有另一种选择 - xpath - 一种定义表达式的方法,有点像regex,但是以XML方式识别。

我建议XML::Twig,因为它没有特别陡峭的学习曲线。第一次:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new -> parsefile ( 'your_file.xml' ); 

print $twig -> get_xpath('//test',0) -> text;

对于你的第二个:

print $twig -> get_xpath('//Test',0) -> att('RequestorId');

这可以是单行 - 如果:

perl -MXML::Twig -0777 -e 'print XML::Twig -> parse ( <> ) -> get_xpath("//test",0) -> text' yourfile

答案 2 :(得分:1)

$xml =~/<test>(.*?)<\/test>/i表达式可以在列表上下文中计算,在这种情况下,它返回一个包含所有捕获组的数组。所以你需要做那样的事情:

($data) = $xml =~/<test>(.*?)<\/test>/i;

编辑:对于第二个示例,如果使用一组括号捕获信息,则可以类似地提取信息:

($RequestorId) = $xml =~ /<Test [^>]*\bRequestorId="([^"]*)"/;