我有一些像这样的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
只是为了检查所有标签是否正确关闭会过度使用吗?
答案 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
# >([^<>]*?)[ ]?\?[ ]?([^<>]+?)<
>
( [^<>]*? )
[ ]?
\?
[ ]?
( [^<>]+? )
<