我有以下字符串输入:
<Name>IncludeLeafPortfolios</Name><DataType>Boolean</DataType><Value>True</Value>
<Name>HierarchyDate</Name><DataType>Int</DataType><IsFixed>false</IsFixed>
<Name>HierarchyDate</Name><DataType>Int</DataType>
<Name>HierarchyDate</Name><DataType>Int</DataType><Value>0</Value><IsFixed>false</IsFixed>
<Name>HierarchyDate</Name><DataType>Int</DataType><Value>0</Value><IsFixed>false</IsFixed>
名称标签始终存在且很有意义。 DataType不感兴趣。 值标记和IsFixed标记可能存在也可能不存在。目标是捕获Value标记,IsFixed标记,如果其中一个存在或两者都存在。
我的解决方案无效:
$element =~ m/^<Name>([\w\s]*)<\/Name>.*([<Value>[\w+\d+]<\/Value>]?)(<IsFixed>[\w+]<\/IsFixed>])?$
请建议。感谢。
答案 0 :(得分:1)
该数据看起来像XML。使用类似XML::LibXML的库解析它,然后对生成的结构执行操作。
不要使用正则表达式来处理XML。 The results are just as bad as trying to use regular expressions for HTML.
答案 1 :(得分:0)
XML是上下文敏感的。正则表达式不是。由于这个原因,您无法使用正则表达式可靠地解析XML。
所以使用解析器。我喜欢XML::Twig
,它会有点像这样:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper;
my $twig = XML::Twig -> new -> parsefile ( 'your_file.xml' );
my @keys = qw ( Name Value IsFixed );
my @rows;
my %current_row;
#iterate children
foreach my $node ( $twig -> root -> children ) {
#extract tag and content
my $tag = $node -> tag;
my $content = $node -> text;
$current_row{$tag} = $content;
#if it's a name tag, assume it's a new row.
if ($tag eq 'Name' and %current_row) {
push @rows, {%current_row};
undef %current_row;
}
}
#output results.
print join ",", @keys, "\n";
foreach my $row ( @rows ) {
print join ",", (map { $row -> {$_} // '' } @keys),"\n";
}
哪个输出:
Name,Value,IsFixed,
IncludeLeafPortfolios,,,
HierarchyDate,True,,
HierarchyDate,,false,
HierarchyDate,,,
HierarchyDate,0,false,
但是,我会注意到你的XML很乱 - 你确定它是如何构建的吗?因为通常,如果您已经关联了&#39;标签,然后他们在一个节点内分组。
e.g。类似的东西:
<xml>
<item>
<Name>HierarchyDate</Name><DataType>Int</DataType><IsFixed>false</IsFixed>
</item>
</xml>
这会大大简化问题,因为你可以:
foreach my $item ( $twig -> root -> children ) {
print join ",", (map { $item -> first_child_text($_) // '' } @keys),"\n";
}