【问题标题】:fast of retrieving data from XML从 XML 中快速检索数据
【发布时间】:2017-01-09 21:41:18
【问题描述】:

我有示例 xml

<?xml version="1.0" encoding="UTF-8"?>
  <tag_1>
     <tag_2>A</tag_2>
     <tag_3>B</tag_3>
     <tag_4>C</tag_4>
     <tag_5>D</tag_5>
  </tag_1>
</xml>

现在我有兴趣只提取特定数据。

例如

tag_1/tag_5 -> D

tag_1/tag_5 是我的数据定义(我想要的唯一数据),它本质上是动态的,这意味着明天 tag_1/tag_4 将是我的数据定义。

所以实际上我的 xml 是一个大型数据集。而这些 xml 有效负载的速度为 50,000/小时到 80,000/小时。

我想知道是否已经有高性能的 xml 阅读器工具或我可以实现的一些特殊逻辑来根据数据定义提取数据。

目前我使用 Stax 解析器进行了实现,但解析 80,000 个 xml 需要将近一天的时间。

public class VTDParser {

    private final Logger LOG = LoggerFactory.getLogger(VTDParser.class);

    private final VTDGen vg;

    public VTDParser() {
        vg = new VTDGen();
    }

    public String parse(final String data, final String xpath) {
        vg.setDoc(data.getBytes());
        try {
            vg.parse(true);
        } catch (final ParseException e) {
            LOG.error(e.toString());
        }

        final VTDNav vn = vg.getNav();
        final AutoPilot ap = new AutoPilot(vn);
        try {
            ap.selectXPath(xpath);
        } catch (final XPathParseException e) {
            LOG.error(e.toString());
        }

        try {
            while (ap.evalXPath() != -1) {
                final int val = vn.getText();
                if (val != -1) {
                    return vn.toNormalizedString(val);
                }
            }
        } catch (XPathEvalException | NavException e) {
            LOG.error(e.toString());
        }
        return null;
    }
}

【问题讨论】:

  • 不知道为什么我得到-1。我不清楚吗?我只是在寻找想法,而不是要求别人为我实施。
  • 50-80,000/小时,也就是每秒 20 个。如果您只工作单线程,这意味着一个 xml 需要 1/20 秒。如果 xml 文件如您所说的非常大,您将永远无法在 0.05 秒内解析它,特别是因为它们可能是您可能无法控制的其他开销(例如,读取 xml 文件时的网络/磁盘延迟)。所以要达到你的目标,你首先需要并行化工作。然后可能会考虑将数据放入数据库中以便于查询,这样您就不必在明天查询更改时重新解析所有文档。但是数据库也需要规划
  • 是的,先生。实际上我最终使用 Vtd-Xml 实现了。我也很想听听你的回答。
  • 好的,我会提交代码sn-p,敬请期待……
  • @vtd-xml-author 所以我发布了代码。如果我只创建一个 VTDParser 实例并继续调用 VTDParser 的 parse 方法而不是 vg.getNav() 以某种异常结束,我会看到一个问题。看不到,因为使用多线程并包装在 Future 中。只有第一次调用以成功结束,其余的都以某种异常结束。

标签: java xml saxparser stax vtd-xml


【解决方案1】:

这是我对您的代码的修改,它编译一次 xpath 并多次重用。它编译 xpath 而不绑定到 VTDNav 实例。它还在退出解析方法之前调用 resetXPath。但是,我没有向您展示如何使用 VTD 对 xml 文档进行预索引...以避免重复解析...。我怀疑它可能是您的差异制造者项目...这是有关 vtd-xml 功能的论文参考。

http://recipp.ipp.pt/bitstream/10400.22/1847/1/ART_BrunoOliveira_2013.pdf

import com.ximpleware.*;


public class VTDParser {
      // private final Logger LOG = LoggerFactory.getLogger(VTDParser.class);

        private final VTDGen vg;
        private final AutoPilot ap;
        public VTDParser() throws VTDException{
            vg = new VTDGen();
            ap = new AutoPilot();
            ap.selectXPath("/a/b/c");// this is how you compile xpath w/o binding to an XML doc
        }

        public String parse(final String data, final AutoPilot ap1) {
            vg.setDoc(data.getBytes());
            try {
                vg.parse(true);
            } catch (final ParseException e) {
                LOG.error(e.toString());
            }

            final VTDNav vn = vg.getNav();
            ap1.bind(vn);
            try {
                while (ap.evalXPath() != -1) {
                    final int val = vn.getText();
                    if (val != -1) {
                        return vn.toNormalizedString(val);
                    }
                }
            } catch (XPathEvalException | NavException e) {
                LOG.error(e.toString());
            }
            ap.resetXPath();// reset your xpath here
            return null;
        }
}

【讨论】:

  • 谢谢。我不明白为什么我们将 AutoPilot ap1 作为参数传递给解析,而不是调用 bind(vn)
  • 那是因为你想重用xpath表达式...对吧?如果你传入一个字符串,那就不再重用了......
  • 嗨。我想知道我们是否可以有这样的东西 "/Anythere here/A/B/C" 。 A、B、C 一直都在。
  • 不明白你的问题,你能为此单独发起一个线程并详细说明吗?
  • 你的意思是/*/A/B/C?
猜你喜欢
  • 2020-02-28
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多