我怎样才能过滤'?'超出XML?

时间:2014-11-05 16:03:21

标签: xml perl

我有一些像这样的XML数据:

<?xml version="1.0"?>
<a>
  <b>someone ? messed up</b>
  <c>this question mark has to disappear too?</c>
</a>

现在我的目标是验证每个开始标记是否有结尾标记,并使用Perl过滤掉<b>标记之间的问号。

我尝试了

的不同变体
$_[0] =~ s|>(.*)\?(.*)<|>$1$2<|g;

但这只会切断<??>。如何在不破坏XML版本标记的情况下使其工作?另外,使用XML::Simple只是为了检查所有标签是否正确关闭会过度使用吗?

3 个答案:

答案 0 :(得分:4)

根据定义 - 破坏的XML被破坏,解析器应该中止而不是尝试验证和修复。这有点令人讨厌,但如果你考虑一下这是有道理的 - 生命太短暂,无法修复格式错误的XML。

然而,我可能会将XML::Twig视为XML处理的模块。循环浏览每个元素并删除&#39;?&#39;从文本中,忽略了XML结构。也许并不像其他答案那样简洁。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new();
local $/;
$twig -> parse ( <DATA> );

my $element = $twig -> root; 

while ( $element = $element -> next_elt() ) {
    my $text_to_change = $element -> text;
    $text_to_change =~ s,\?,,g;
    $element -> set_content ( $text_to_change );
 }

$twig -> set_pretty_print('indented');
$twig -> print;


__DATA__
<?xml version="1.0"?>
<a>
    <b>someone ? messed up</b>
    <c>this question mark has to disappear too?</c>
</a>

我们正在使用XML :: Twig来解析您的XML(这是有效的,但包含问号)。 在打印重新格式化的缩进的XML块之前,循环遍历每个元素,提取元素文本 - 从而省略标记和属性(如XML Doctype),然后修改它。 (&#39;漂亮&#39;打印有各种格式选项)。

如果你的标签坏了,并告诉你它们在哪里,这将会出错,但它不会修复它们。

答案 1 :(得分:3)

  

现在,我的目标是过滤<b>代码中的问号

XML :: LibXML解决方案:

for my $text_node ($doc->findnodes('//b//text()')) {
    my $text = $text_node->data();
    $text =~ s/\?//g;
    $text_node->setData($text);
}

如果你有Perl 5.14+,可以简化为

for my $text_node ($doc->findnodes('//b//text()')) {
    $text_node->setData( $text_node->data() =~ s/\?//gr );
}

$_->setData( $_->data() =~ s/\?//gr )
   for $doc->findnodes('//b//text()');

答案 2 :(得分:0)

正则表达式可能不是修复 XML的最佳解决方案。

要修复你的问号正则的正则表达式 有点有缺陷的正则表达式。有缺陷,因为它只修复了一个?

s/>([^<>]*?)[ ]?\?[ ]?([^<>]+?)</>$1 $2</g

 #  >([^<>]*?)[ ]?\?[ ]?([^<>]+?)<

 >
 ( [^<>]*? )
 [ ]? 
 \?
 [ ]? 
 ( [^<>]+? )
 <