我编写了一个C#应用程序来解析非常大的(100MB +)XML文件。
我完成它的方式是我使用System.Xml.XmlReader
遍历文件,然后,一旦我到达最终节点,我需要从中收集值,我将每个非常小的元素转换为{ {1}}并通过System.Xml.Linq.XElement
执行各种XPath语句以获取我需要的数据。
这非常有效且效率很高,但由于XEelement.XPathEvaluate
仅支持XPath 1.0而我的语句是XPath 2.0(问题发布为here},因此我有时会收到错误的数据。 )。
我最初这样做的代码看起来如下:
XPathEvaluate
根据我在上一个问题中提出的建议,我认为最好的解决方案是从void parseNode_Old(XmlReader rdr, List<string> xPathsToExtract)
{
// Enter the node:
rdr.Read();
// Load it as an XElement so as to be able to evaluate XPaths:
var nd = XElement.Load(rdr);
// Loop through the XPaths related to that node and evaluate them:
foreach (var xPath in xPathsToExtract)
{
var xPathVal = nd.XPathEvaluate(xPath);
// Do whatever with the extracted value(s)
}
}
转移到System.Xml
(它支持XPath 2.0),我当前更新的代码如下:< / p>
Saxon.Api
这是有效的(对我的XPath进行了一些其他更改),但速度变慢了大约5-10倍。
这是我第一次使用Saxon.Api库,这就是我想到的。我希望有更好的方法来实现这一目标,以使代码执行速度具有可比性,或者,如果有人对如何以更好的方式评估XPath 2.0语句有其他想法而没有大量的重写,I&I #39;我喜欢听他们!
非常感谢任何帮助!!
谢谢!
更新
在尝试自己解决这个问题时,我将以下两个语句移到了构造函数中:
void parseNode_Saxon(XmlReader rdr, List<string> xPathsToExtract)
{
// Set up the Saxon XPath processors:
Processor processor = new Processor(false);
XPathCompiler compiler = processor.NewXPathCompiler();
XdmNode nd = processor.NewDocumentBuilder().Build(rdr);
// Loop through the XPaths related to that node and evaluate them:
foreach (var xPath in xPathsToExtract)
{
var xPathVal = compiler.EvaluateSingle(xPath, (XdmNode)childNode);
// Do whatever with the extracted value(s)
}
}
而不是每次调用此方法时不断重新创建它们已经大大帮助了,但是该过程仍然比原生Processor processor = new Processor(false);
XPathCompiler compiler = processor.NewXPathCompiler();
版本慢大约3倍。关于如何实现此解析器的任何其他想法/想法?
答案 0 :(得分:1)
这可能是您使用此设置所能做到的最佳效果。
Saxon on .NET的速度通常是Saxon在Java上慢3-5倍,原因我们从未深入到底。我们目前正在探索使用Excelsior JET而非IKVMC重建它的可能性,看看这是否可以加快速度。
Saxon在第三方DOM实现上比在其自己的本机树表示上慢得多,但似乎您已经更改了代码以使用本机树模型。
由于您每次执行时都要解析每个XPath表达式,因此您的性能可能会受XPath编译时间的影响(即使您正在搜索大型XML文档)。直到最近,Saxon的编译时性能很少受到关注,因为我们认为在编译时做更多工作以节省运行时的工作总是值得的;但在这种情况下,情况显然并非如此。可能值得拆分编译和运行时并单独测量,只是为了看看是否给出了任何见解。例如,它可能会建议关闭一些优化选项。显然,如果你可以缓存和重用已编译的XPath表达式,这将有所帮助。