从大型xml文件中提取大xml块的最佳方法

时间:2017-07-31 08:48:58

标签: java xml xpath xquery sax

我使用XPath从XML文件中提取大块。我的xml文件很大,它们来自PubMed。我的文件类型的一个例子是:

ftp://ftp.ncbi.nlm.nih.gov/pubmed/baseline/medline17n0001.xml.gz

所以,使用

 Node result = (Node)xPath.evaluate("PubmedArticleSet/PubmedArticle[MedlineCitation/PMID = "+PMIDtoSearch+"]", doc, XPathConstants.NODE);

我收到PMIDtoSearch的文章,所以它很完美。但这需要很长时间。我必须做大约800.000次,所以使用这个解决方案需要两个多月。有些块有超过400行,每个xml文件有超过4百万行。

我也尝试了类似getElementsByTagName函数的解决方案,但它几乎需要相同的时间。

您知道如何改进解决方案吗?

感谢。

3 个答案:

答案 0 :(得分:4)

我把你的文件加载到exists-db然后执行你的查询,基本上是这样的:

xquery version "3.0";
let $medline := '/db/Medline/Data'
let $doc := 'medline17n0001.xml'
let $PMID := request:get-parameter("PMID", "")
let $article := doc(concat($medline,'/',$doc))/PubmedArticleSet/PubmedArticle[MedlineCitation/PMID=$PMID]
return
$article

文档在400毫秒内从远程服务器返回。如果我加强了那个服务器,我会期望少于那个,它可以处理多个并发请求。或者如果你在当地拥有更快的东西。

亲自尝试,我将数据留在测试服务器中(并记住这是在远程查询加利福尼亚的亚马逊微服务器):

http://54.241.15.166/get-article2.xq?PMID=8

http://54.241.15.166/get-article2.xq?PMID=6

http://54.241.15.166/get-article2.xq?PMID=1

当然,整个文件都在那里。您只需将该查询更改为PMID = 667或999或其他任何内容,然后返回目标文档片段。

答案 1 :(得分:2)

正如@KevinBrown建议的那样,数据库可能是正确的答案。但是,如果这是一次性流程,那么可能解决方案比您的解决方案更快,但不需要学习如何设置XML数据库的复杂性。

在您使用的方法中,有两个主要成本:解析XML文档以在内存中创建树,然后搜索内存中的文档以查找特定的ID值。我猜想解析成本可能比搜索成本高出一个数量级。

因此,有两个要素可以获得良好的表现:

  • 首先,您需要确保只解析每个源文档一次(而不是每个查询一次)。你还没告诉我们足够让我知道你是否已经这样做了。

  • 第二,如果要从单个文档中检索许多数据块,则需要在不对每个文档进行序列搜索的情况下执行此操作。实现此目的的最佳方法是使用构建索引的查询处理器来优化查询(例如Saxon-EE)。或者,您可以“手动”构建索引,例如使用XQuery 3.1映射,或者使用XSLT中的xsl:key功能。

答案 2 :(得分:0)

这是在我的笔记本电脑上执行xpath查询的代码..结果看起来不错......不管pmid值如何都需要大约1秒。你打算如何提取文本。我可以更新代码来定位。

['class' => 'yii\grid\ActionColumn',
             'template' => '{view}&nbsp{update}&nbsp{delete}',   //{view} 
             'buttons' => [
                 'view' => function($url, $model)   {
                        return Html::a('<button class="btn btn-success">View &nbsp;<i class="glyphicon glyphicon-eye-open"></i></button>',$url);
                    },
                 'update' => function($url, $model) {
                        return Html::a('<button class="btn btn-primary">Update &nbsp;<i class="glyphicon glyphicon-pencil"></i></button>',$url);
                    },
                 'delete' => function($url, $model) {
                      return Html::a('<button class="btn btn-danger">Delete &nbsp;<i class="glyphicon glyphicon-trash"></i></button>', $url, 
                             ['data-confirm' => 'Are you sure you want to delete this item?', 'data-method' =>'POST']
                          );
                    },
                'urlCreator' => function($action, $model, $key, $index) {
                      if ($action == 'view') {
                          return Html::a('Action', $url);
                      }
                      if ($action == 'update') {
                         return Html::a('Action', $url);
                      }
                      if ($action == 'delete') {
                          return Html::a('Action', $url);
                      }
                    } 
              ],            
            ],  // fin ActionColumn