【问题标题】:Best way to extract big xml block from large xml file从大 xml 文件中提取大 xml 块的最佳方法
【发布时间】:2017-07-31 08:48:57
【问题描述】:

我正在使用 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文件超过400万行。

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

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

谢谢。

【问题讨论】:

  • 我会编写 XQuery 来获取 GZIP,将其解压缩并存储到存在数据库中。然后针对该存储的文档编写 Xquery。
  • 您的连接可能受到网络服务的限制。

标签: java xml xpath xquery sax


【解决方案1】:

我将您的文档加载到存在数据库中,然后执行您的查询,基本上是这样的:

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 或其他任何值,然后取回目标文档片段。

【讨论】:

    【解决方案2】:

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

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

    因此,要获得良好的性能,有两个要素:

    • 首先,您需要确保每个源文档只解析一次(而不是每个查询一次)。你没有告诉我们足够多的信息,我无法判断你是否已经这样做了。

    • 其次,如果您要从单个文档中检索许多数据块,您希望这样做而不需要对每个数据进行串行搜索。实现这一点的最佳方法是使用构建索引以优化查询的查询处理器(例如 Saxon-EE)。或者,您可以“手动”构建索引,例如使用 XQuery 3.1 映射,或使用 XSLT 中的 xsl:key 特性。

    【讨论】:

    • 这是一个好点。我熟悉的数据集合。它大约是 21,000 MB 的数据。如果要处理一次,也许。再说一次,我可以作弊,因为我有一个很棒的 Amazon 服务器镜像,带有存在数据库和更多加载,我可以在 5 分钟内启动。
    【解决方案3】:

    这是执行 xpath 查询的代码.. 在我的笔记本电脑上,结果看起来不错.. 无论 pmid 值如何,它都花费了大约 1 秒。您打算如何提取文本。我可以更新代码以针对它。

    public static void main(String[] args) throws VTDException{
            VTDGen vg = new VTDGen();
            if (!vg.parseFile("d:\\xml\\medline17n0001.xml", false))
                return;
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            System.out.println("nesting level"+vn.getNestingLevel());
            String PMIDtoSearch =  "30000";
            ap.selectXPath("/PubmedArticleSet/PubmedArticle[MedlineCitation/PMID = "+PMIDtoSearch+"]");
            System.out.println("====>"+ap.getExprString());
            int i=0,count=0;
            System.out.println(" token count ====> "+ vn.getTokenCount() );
            while((i=ap.evalXPath())!=-1){
                count++;
                System.out.println("string ====>"+vn.toString(i));
            }
            System.out.println(" count ===> "+count);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-23
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      相关资源
      最近更新 更多