加速xpath
我有一个1000条目文档的格式是这样的
这里有超过1000个Entry节点。 我正在编写一个Java程序,它基本上逐个获取所有节点并对每个节点进行一些分析。 但问题是节点的检索时间随着它的增加而增加。 例如,检索第一个节点100毫秒以检索第二个节点需要78毫秒,并且它继续增加。 要检索999节点,它需要超过5秒。 这非常慢。 我们将此代码插入到包含超过1000个条目的XML文件中。 有些像数百万。 解析整个文档的总时间超过5分钟。
我正在使用这个简单的代码来遍历它。 这里nxp
是我自己的类,它有从xpath获取节点的所有方法。
nxp.fromXpathToNode("/Example/Entry" + "[" + i + "]", doc);
和doc
是该文件的文档。 i
是要检索的节点。
当我尝试这样的事情时
List nl = nxp.fromXpathToNodes("/Example/Entry",doc); content = nl.get(i);
我面临同样的问题。
任何人都有任何关于如何加速节点tretirival的解决方案,因此从XML文件获取第一个节点和1000个节点需要相同的时间。
谢谢
这是xpathtonode的代码。
public Node fromXpathToNode(String expression, Node context) { try { return (Node)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODE); } catch (Exception cause) { throw new RuntimeException(cause); } }
这是fromxpathtonodes的代码。
public List fromXpathToNodes(String expression, Node context) { List nodes = new ArrayList(); NodeList results = null; try { results = (NodeList)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODESET); for (int index = 0; index < results.getLength(); index++) { nodes.add(results.item(index)); } } catch (Exception cause) { throw new RuntimeException(cause); } return nodes; }
这是开始
公共类NativeXpathEngine实现XpathEngine
{
私有的最终XPathFactory工厂;
private final XPath engine; /** * Cache for previously compiled XPath expressions. {@link XPathExpression#hashCode()} * is not reliable or consistent so use the textual representation instead. */ private final Map cachedExpressions; public NativeXpathEngine() { super(); this.factory = XPathFactory.newInstance(); this.engine = factory.newXPath(); this.cachedExpressions = new HashMap(); }
试试VTD-XML 。 它比DOM使用更少的内存。 它比SAX更容易使用并支持XPath。 以下是一些示例代码,可帮助您入门。 它应用XPath来获取Entry元素,然后打印出n1和n2子元素。
final VTDGen vg = new VTDGen(); vg.parseFile("/path/to/file.xml", false); final VTDNav vn = vg.getNav(); final AutoPilot ap = new AutoPilot(vn); ap.selectXPath("/Example/Entry"); int count = 1; while (ap.evalXPath() != -1) { System.out.println("Inside Entry: " + count); //move to n1 child vn.toElement(VTDNav.FIRST_CHILD, "n1"); System.out.println("\tn1: " + vn.toNormalizedString(vn.getText())); //move to n2 child vn.toElement(VTDNav.NEXT_SIBLING, "n2"); System.out.println("\tn2: " + vn.toNormalizedString(vn.getText())); //move back to parent vn.toElement(VTDNav.PARENT); count++; }
正确的解决方案是在调用item(i)后立即分离节点,如下所示:
Node node = results.item(index) node.getParentNode().removeChild(node) nodes.add(node)
请参阅XPath.evaluate性能在多个调用中减慢(荒谬)
我在Xpath评估中遇到了类似的问题,我尝试使用CachedXPathAPI,它比之前使用的XPathApi快100倍。 有关此Api的更多信息,请访问: http : //xml.apache.org/xalan-j/apidocs/org/apache/xpath/CachedXPathAPI.html
希望能帮助到你。 干杯,Madhusudhan
如果您需要解析大而扁平的文档,SAX是一个不错的选择。 它允许您将XML作为流处理,而不是构建一个巨大的DOM。 您的示例可以使用ContentHandler进行解析,如下所示:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.ext.DefaultHandler2; public class ExampleHandler extends DefaultHandler2 { private StringBuffer chars = new StringBuffer(1000); private MyEntry currentEntry; private MyEntryHandler myEntryHandler; ExampleHandler(MyEntryHandler myEntryHandler) { this.myEntryHandler = myEntryHandler; } @Override public void characters(char[] ch, int start, int length) throws SAXException { chars.append(ch); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("Entry".equals(localName)) { myEntryHandler.handle(currentEntry); currentEntry = null; } else if ("n1".equals(localName)) { currentEntry.setN1(chars.toString()); } else if ("n2".equals(localName)) { currentEntry.setN2(chars.toString()); } } @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { chars.setLength(0); if ("Entry".equals(localName)) { currentEntry = new MyEntry(); } } }
如果文档具有更深且更复杂的结构,则您将需要使用Stacks来跟踪文档中的当前路径。 然后你应该考虑编写一个通用的ContentHandler来做脏工作并与你的文档类型相关的处理程序一起使用。
你使用什么样的解析器?
DOM将整个文档拉入内存 – 一旦将整个文档拉入内存中,您的操作就会很快,但在Web应用程序或for循环中这样做可能会产生影响。
SAX解析器按需解析并在您请求时加载节点。
因此,尝试使用适合您需要的解析器实现。
将JAXEN库用于xpath: http ://jaxen.codehaus.org/
- 如何设置JPanel的透明背景?
- 新的JUnit 4.8.1 @Category渲染测试套件几乎已经过时了吗?
- liquibase 3.5.X找不到包含相对路径的includeAll的任何文件
- 如何使用cascade =“all,delete-orphan”制作hibernate集合的副本
- Java三元运算符(?:)不起作用; 第二个或第三个操作数返回布尔值
- org.glassfish.jersey.server.model.ModelValidationException:应用程序初始化期间应用程序资源模型的validation失败
- 如何解析JSON文件?
- 通用树,自有界generics
- 从Java运行.py文件