根据ID列表过滤XML文档



i具有TREC格式的7GB XML文档。该文件具有标签DOC,其中有DOCNOTEXT

<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 仅在文件>文件中具有DOCNODOC 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>元素,读取下一个元素并提取其文本,该文本与 abcghi使用正则表达式进行比较,仅在匹配的情况下仅打印该部分树。

像以下方式运行:

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>

相关内容

  • 没有找到相关文章

最新更新