2012-04-03 58 views
1

我有本质上的XPath的名单像这样一个文件:XPathSelectElement非常慢;有没有更好的方法让XPath获得价值?

/Options/File[1]/Settings[1]/Type[1] 
/Options/File[1]/Settings[1]/Path[1] 
/Options/File[1]/Settings[2]/Type[1] 
/Options/File[1]/Settings[2]/Path[1] 
/Options/File[2]/Settings[1]/Type[1] 
/Options/File[2]/Settings[1]/Path[1] 

我需要抓住从元素的值在中等大小的XML文件中指出,从这些XPath(〜3-5MB)。使用XPathSelectElement运行良好,但速度非常慢。有没有更快的方法来执行Linq到XML或甚至手动遍历XML?

在相关问题中,XPath中的索引值和XElement返回的元素顺序保证是相同的?例如,将这些返回相同的:

xdoc.XPathSelectElement("/Options/File[1]/Settings[2]); 

xdoc.root.Elements("File").ElementAt(0).Elements("Settings").ElementAt(1); 
+1

'这些会返回相同的吗?你为什么不尝试? – 2012-04-03 21:38:51

+1

我当之无愧。对于什么是值得的,我实现了一个遍历元素的方法,有效地做了与“xdoc.root.Elements(”File“)相同的事情。 它似乎确实匹配,至少对我的数据。但即使对于大数据集,我也不会说可以保证这些方法之间的索引总是相同的。 如果此方法成立,它似乎比使用XPathSelectElement快至少一个数量级。 – 2012-04-03 22:12:46

回答

1

我想这就是我要去的。我确信可以有更多的性能改进,比如Alexei的建议,但是在我的有限测试中,这已经至少快了10倍。

private XElement GetElementFromXPath(XDocument xDoc, string xPath) 
    { 
     string[] nodes = xPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 
     XContainer xe = xDoc.Root; 
     for (int i = 1; i < nodes.Length; i++) 
     { 
      string[] chunks = nodes[i].Split(new char[] { '[', ']' }); 

      int index = 0; 
      if (Int32.TryParse(chunks[1], out index)) 
       xe = xe.Elements(chunks[0]).ElementAt(index - 1); 
     } 
     return (XElement)xe; 
    } 

这假定根以外的所有元件与在XPath(这是真对我的情况下)它们的索引号一起列出。

2

索引的XPath(第n个孩子)通常是缓慢的,由于需要向上遍历所有的孩子,你需要的人。要检查相对较大的文件,请尝试挑选第一个孩子和最后一个孩子,并比较差异(重复约1000次,并使用StopWatch进行测量)。

如果您的XPath完全如您所示,您可能可以通过在迭代时缓存子节点来手动进行选择。

XML中元素的顺序很重要,所以普通的XML API将始终保持元素的顺序。请注意,对于XML而言,属性的顺序并不重要,因此在查询中(不太可能,但理论上可能)和跨不同API的属性顺序可能不尽相同。

+0

谢谢阿列克谢 - 你的订单说明是我关心的问题。 – 2012-04-03 22:27:49

1

我刚刚有一个类似的问题,你:我有一个可怕的表现,选择一个中等大小的XML文件(3 MB)中的一些节点,使用一堆索引XPath表达式。

但与您的解决方案相反,我没有在XPath表达式的每个部分都有索引。所以我尝试使用XPath将LINQ转换为XML(XElement.XPathSelectElement),但是通过创建XPathDocument并调用CreateNavigator()来使用XPathNavigator。在我使用的导航器上SelectSingleNode

使用XElement.XPathSelectElement我花了137.3秒完成所有选择(剩下的程序只用了大约3秒)。

使用XPathNavigator.SelectSingleNode的选择现在需要1.2秒诠释总...这是近115

所以,如果有人需要更快的XPath查询,不希望解析查询自己的一个因素:不使用LINQ如果可能的话,以XML来看,它似乎是明智的执行可怕的表现。

相关问题