i具有TREC格式的7GB XML文档。该文件具有标签DOC
,其中有DOCNO
和TEXT
。
<FILE>
<DOC>
<DOCNO>abc</DOCNO>
<TEXT>content
of first
doc</TEXT>
</DOC>
<DOC>
<DOCNO>def</DOCNO>
<TEXT>content
of second
doc</TEXT>
</DOC>
<DOC>
<DOCNO>ghi</DOCNO>
<TEXT>content
of third
doc</TEXT>
</DOC>
</FILE>
我想过滤此文档和 keep 仅在文件>文件中具有DOCNO
的DOC
s 包含ID列表:
abc
ghi
因此输出变为
<FILE>
<DOC>
<DOCNO>abc</DOCNO>
<TEXT>content
of first
doc</TEXT>
</DOC>
<DOC>
<DOCNO>ghi</DOCNO>
<TEXT>content of
third
doc</TEXT>
</DOC>
</FILE>
我的猜测是xml_grep
应该有用,但我做不到。
如果您有xml_grep
,我假设还安装了Perl模块XML::Twig
。我不知道xml_grep
是如何工作的,但是您可以通过完整的脚本获得相同的结果,例如:
#!/usr/bin/env perl
use warnings;
use strict;
use XML::Twig;
XML::Twig->new(
twig_print_outside_roots => 1,
twig_roots => {
'DOC' => sub {
my $docno = $_->next_elt('DOCNO') || next;
if ( $docno->text_only =~ m/A(?:abc|ghi)Z/ ) {
$_->print;
}
},
},
pretty_print => 'indented',
)->parsefile( shift );
它搜索每个 <DOC>
元素,读取下一个元素并提取其文本,该文本与 abc
或 ghi
使用正则表达式进行比较,仅在匹配的情况下仅打印该部分树。
像以下方式运行:
perl script.pl xmlfile
产生的
(注意空间都不是有意义的,因为它们不超出任何元素):
<FILE>
<DOC>
<DOCNO>abc</DOCNO>
<TEXT>content
of first
doc</TEXT>
</DOC>
<DOC>
<DOCNO>ghi</DOCNO>
<TEXT>content
of third
doc</TEXT>
</DOC>
</FILE>
使用awk创建XPath和XMlstarlet来过滤文档:
$ xpath=$(awk '
BEGIN {printf "//DOC[not("}
{printf "%sDOCNO="%s"", sep, $0; sep=" or "}
END {print ")]"}
' ids.txt)
$ echo "$xpath"
//DOC[not(DOCNO="abc" or DOCNO="ghi")]
$ xmlstarlet ed -O -d "$xpath" file.xml
<FILE>
<DOC>
<DOCNO>abc</DOCNO>
<TEXT>content
of first
doc</TEXT>
</DOC>
<DOC>
<DOCNO>ghi</DOCNO>
<TEXT>content
of third
doc</TEXT>
</DOC>
</FILE>