Edit2:请使用正则表达式匹配解决方案。谢谢!
编辑:我正在寻找正则表达式解决方案,如果它存在的话。我有其他块具有相同的非XML数据,我不能使用Perl,我添加了Perl标签,因为我更熟悉Perl中的正则表达式。提前谢谢!
我的列表如下:
<Param name="Application #" value="1">
<Param name="app_id" value="32767" />
<Param name="app_name" value="App01" />
<Param name="app_version" value="1.0.0" />
<Param name="app_priority" value="1" />
</Param>
<Param name="Application #" value="2">
<Param name="app_id" value="3221" />
<Param name="app_name" value="App02" />
<Param name="app_version" value="1.0.0" />
<Param name="app_priority" value="5" />
</Param>
<Param name="Application #" value="3">
<Param name="app_id" value="32" />
<Param name="app_name" value="App03" />
<Param name="app_version" value="1.0.0" />
<Param name="app_priority" value="2" />
</Param>
如果我只知道app_name的值,如何为一个应用程序获取一个块。例如对于App02我想要
<Param name="Application #" value="2">
<Param name="app_id" value="3221" />
<Param name="app_name" value="App02" />
<Param name="app_version" value="1.0.0" />
<Param name="app_priority" value="5" />
</Param>
是否可以获取它,如果其他“name =”行未知(但总是name="app_name"
和Param name="Application #"
)?
可以在单个正则表达式匹配中完成吗? (不一定是,但感觉可能有办法)。
答案 0 :(得分:4)
因为您的内容似乎是某些XML,为什么不使用真正的解析器来完成任务呢?
use XML::XPath;
use XML::XPath::XMLParser;
my $xp = XML::XPath->new(filename => 'test.xhtml');
my $nodeset = $xp->find('/Param[@name=\'Application #\']'); # find all applications
foreach my $node ($nodeset->get_nodelist) {
print "FOUND\n\n",
XML::XPath::XMLParser::as_string($node),
"\n\n";
}
我建议你不使用reg exp来执行该任务,因为它会变得复杂而且无法维护。
note :也可以使用DOM API取决于您最喜欢的那个。
答案 1 :(得分:3)
这似乎是bogus XML的悲惨案例。错误地尝试创造enterprisey software充其量。开发人员可以使用合理的配置文件格式,例如:
[App03] app_id = 32767 app_version = 1.0.0 ...
但他们决定用无意义的BSXML驱使每个人疯狂。
我想说,如果此文件的大小小于10 MB,请继续使用XML::Simple。如果文件确实只包含 完全 的重复块,则可以使用以下解决方案:
#!/usr/bin/perl
use strict; use warnings;
my %apps;
{
local $/ = "</Param>\n";
while ( my $block = <DATA> ) {
last unless $block =~ /\S/;
my %appinfo = ($block =~ /name="([^"]+?)"\s+value="([^"]+?)"/g);
$apps{ $appinfo{app_name} } = \%appinfo;
}
}
use Data::Dumper;
print Dumper $apps{App03};
编辑:如果你不能使用Perl并且你不会告诉我们你可以使用什么,那么我无能为力但是指出
/name="([^"]+?)"\s+value="([^"]+?)"/g
会为您提供所有name
- value
对。
答案 2 :(得分:1)
似乎使用XML阅读器库更合适,但我不知道Perl足以建议一个。
答案 3 :(得分:1)
Perl的XML DOM Parser可能适用于此。
答案 4 :(得分:1)
我也更喜欢解析器解决方案。如果你绝对 使用正则表达式并理解这种方法的所有缺点,那么以下正则表达式应该可以工作:
<Param name="Application #"[^>]*>\s+<Param[^>]*>\s+<Param name="app_name" value="App02" />\s+(?:<Param[^>]*>\s+){2}</Param>
这在很大程度上依赖于示例中的结构。标签的重新排序,附加标签的引入或标签的(颤抖)嵌套将破坏正则表达式。
答案 5 :(得分:1)
我建议使用XML解析器之一,但如果你不能这样做,那么下面的快速和脏代码应该这样做:
my ($rez) = $data =~/\<Param\s+name\s*=\s*"Application\s#"\s+value\s*=\s*"2"\>((?:.|\n)*?)^\<\/Param\>/m;
print $rez;
(假设$ data包含您的xml作为单个字符串,可能是多行)