我有一个解析2个XML的子例程,一个是原始日志数据,另一个是过滤器。我想从log.xml中删除其中一个筛选器中找不到的所有内容。多次解析XML文件并将结果合并在一起
这是我的日志文件的例子:
<log>
<message>
<type>warning</type>
<from>cody</from>
<content>cant use XML::Merge</content>
</message>
<message>
<type>error</type>
<from>cody</from>
<content>some text here</content>
</message>
<message>
<type>warning</type>
<from>charlie</from>
<content>ruff</content>
</message>
<message>
<type>error</type>
<from>cody</from>
<content>an error</content>
</message>
</log>
与filter.xml看起来像:
<filters>
<filter>
<type>warning</type>
<content>XML::Merge</content>
</filter>
<filter>
<type>error</type>
</filter>
</filters>
这将导致包含内容的所有警告“XML ::合并“被保留和所有错误。我试图用第一个过滤器进行第一次传递,这导致所有其他消息节点被切断,所以我在得到的XML文件中没有错误。接下来的过滤器会剔除第一个过滤器应该保留的过滤器。这里是我的代码,如果在filter.xml中只有一个过滤器,那么运行良好。
sub include {
my $filterParser = XML::LibXML->new->parse_file($filterXML);
my $logParser = XML::LibXML->new->parse_file($xml);
foreach my $filter ($filterParser->findnodes('/filters/filter')) {
foreach my $msg ($logParser->findnodes('/log/message')) {
foreach my $msgNode ($msg->childNodes) {
foreach my $filterNode ($filter->childNodes) {
if ($msgNode->localName eq $filterNode->localName) {
my $m = $msgNode->textContent;
my $f = $filterNode->textContent;
if (index($m, $f) == -1) {
$msg->parentNode->removeChild($msg);
}
}
}
}
}
}
$logParser->toFile($xml);
}
我明白为什么它输出与多个过滤器一个空白文档,但需要帮助上获得第一遍的地方保存,然后用原始的XML做出通过用第二过滤器,等等,直到没有剩余的过滤器,然后将所有内容合并成一个XML,而没有重复的消息。
我可能会写你的过滤器的文件转换成执行过滤XSLT文件XSLT文件。 – reinierpost 2015-03-25 11:16:24
@reinierpost是的,我有点希望我走了那条路,但已经沉浸在LibXML中,并不想开始学习别的东西。似乎最好坚持我习惯的方式。 – 2015-03-25 14:38:05
@reinierpost也,是不是增加了一个额外的步骤?将filter.xml转换为XSLT,然后执行过滤器?我认为我提出的解决方案可能不适用于大型log.xml文件(尚未尝试过),但是我认为当节点被标记为保留时,我可以使用更多的标志来加速它以打破循环当然。 – 2015-03-25 14:41:30