是否有针对提供的 XML 文档进行 XPath 表达式流式计算的生产就绪库?我的调查表明,大多数现有解决方案在评估 XPath 表达式之前会将整个 DOM 树加载到内存中。
是否有针对提供的 XML 文档进行 XPath 表达式流式计算的生产就绪库?我的调查表明,大多数现有解决方案在评估 XPath 表达式之前会将整个 DOM 树加载到内存中。
考虑到XPath语法允许以下内容,这是否适用于完整的XPath实现:
/AAA/XXX/following::*
并且
/AAA/BBB/following-sibling::*
这意味着需要向前查看的要求?也就是说,从特定节点开始,您将不得不加载整个文档。
Nux库的文档(特别是StreamingPathFilter)指出了这一点,并引用了一些依赖于XPath的子集的实现。Nux声称执行一些流查询功能,但考虑到上述限制,XPath实现方面会有一些限制。
有几个选择:
DataDirect Technologies出售一种XQuery实现,采用投影和流式处理,可以处理多达数GB的文件 - 例如比可用内存更大。它是一个线程安全库,易于集成。仅限Java。
Saxon是一个开源版本,还有一个价格适中的更昂贵的版本,在某些情况下可以进行流式处理。 Java,但也有 .net 版本。
虽然我没有实际经验,但我觉得值得提一下 QuiXProc(http://code.google.com/p/quixproc/)。它是一种流式处理 XProc 的方法,使用提供 XPath 流支持等库。
顺便说一下,我已经使用了Nux流过滤器xpath查询来处理非常大的(> 3GB)文件,它既可以完美地工作,又几乎不占用内存。我的用例略有不同(不是验证为中心),但我强烈鼓励您尝试使用Nux。
我想我会选择自定义代码。如果只想读取xml文档的一些路径,.NET库可以让我们接近目标。
由于迄今为止我看到的所有解决方案都只尊重XPath子集,因此这也是这种类型的解决方案。不过,子集确实非常小。 :)
这段C#代码读取xml文件并计算给定显式路径的节点数。您还可以轻松操作属性,使用xr["attrName"]
语法。
int c = 0;
var r = new System.IO.StreamReader(asArgs[1]);
var se = new System.Xml.XmlReaderSettings();
var xr = System.Xml.XmlReader.Create(r, se);
var lstPath = new System.Collections.Generic.List<String>();
var sbPath = new System.Text.StringBuilder();
while (xr.Read()) {
//Console.WriteLine("type " + xr.NodeType);
if (xr.NodeType == System.Xml.XmlNodeType.Element) {
lstPath.Add(xr.Name);
}
// It takes some time. If 1 unit is time needed for parsing the file,
// then this takes about 1.0.
sbPath.Clear();
foreach(object n in lstPath) {
sbPath.Append('/');
sbPath.Append(n);
}
// This takes about 0.6 time units.
string sPath = sbPath.ToString();
if (xr.NodeType == System.Xml.XmlNodeType.EndElement
|| xr.IsEmptyElement) {
if (xr.Name == "someElement" && lstPath[0] == "main")
c++;
// And test simple XPath explicitly:
// if (sPath == "/main/someElement")
}
if (xr.NodeType == System.Xml.XmlNodeType.EndElement
|| xr.IsEmptyElement) {
lstPath.RemoveAt(lstPath.Count - 1);
}
}
xr.Close();