我有一個解析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