如何删除两个XML标记之间的所有空格?

时间:2016-01-05 21:18:45

标签: regex perl replace

我有一个Perl脚本,我想修改它以删除两个XML标记之间的空格。

示例XML:

<TAG>
<TAG1><TAG2>abc 123 def 456 ... </TAG2></TAG1><TAG1><TAG2>xyz 987 ... </TAG>

我想删除所有TAG2标记之间出现的所有空格。我尝试了以下方法:

$vModStrg =~ s/(<TAG2>(.*?)<\/TAG2>)/<TAG2>zzzzzz<\/TAG2>/g;

但这会将整个匹配替换为zzzzz。如何告诉Perl只删除TAG2所有匹配项的匹配空格?

1 个答案:

答案 0 :(得分:2)

正则表达式对于这项工作来说是一个糟糕的工具,因为解析XML需要递归。您可以使用较新版本的正则表达式来实现这一点,但最多会导致非常复杂且难以阅读的正则表达式,以及具有边缘情况的正则表达式,这些正则表达式将会中断。

请参阅:Why it's not possible to use regex to parse HTML/XML: a formal explanation in layman's terms

所以使用解析器 - 删除<TAG2>元素之间的空格&#39;:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig; 

#parse the data from our "DATA" filehandle. 
#you might want "parsefile('somefilename.xml')" instead. 
my $twig = XML::Twig -> parse ( \*DATA );

#iterate 'text' below "TAG2" anywhere in the document. 
foreach my $tag ( $twig -> get_xpath ('//TAG2/#TEXT') ) {
    #modify this tag. 
    $tag -> set_text($tag -> text =~ s/\s+//gr ); 
}
#set output options
$twig -> set_pretty_print('indented_a');
#print to STDOUT. You might want:
#print {$output_fh} $twig -> sprint; 
$twig -> print;

__DATA__
<root>
   <TAG2>words with spaces</TAG2>
   <TAG2>
       <child>wordswordswords more words
       </child>
   </TAG2>
   <TAG1>some more words with spaces</TAG1>
   <TAG2>something here
       <another_child att="fish" />
   </TAG2>
</root>

输出:

<root>
  <TAG2>wordswithspaces</TAG2>
  <TAG2>
    <child>wordswordswords more words
       </child>
  </TAG2>
  <TAG1>some more words with spaces</TAG1>
  <TAG2>somethinghere<another_child att="fish" /></TAG2>
</root>

正如您所看到的 - 正确修改<TAG2>元素之间的文本,并保持其他内容不变。对于奖励积分,它至少同样清楚它作为同等正则表达式所做的事情!